summaryrefslogtreecommitdiffstats
path: root/src/designer
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit50123887ba0f33cf47520bee7c419d68742af2d1 (patch)
tree0eb8679b9e4e4370e59b44bfdcae616816e39aca /src/designer
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/designer')
-rw-r--r--src/designer/data/generate_header.xsl465
-rw-r--r--src/designer/data/generate_impl.xsl1161
-rw-r--r--src/designer/data/generate_shared.xsl331
-rw-r--r--src/designer/data/ui3.xsd353
-rw-r--r--src/designer/data/ui4.xsd589
-rw-r--r--src/designer/designer.pro5
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor.cpp446
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor.h92
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor.pri16
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_global.h57
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_instance.cpp50
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_plugin.cpp133
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_plugin.h93
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_tool.cpp111
-rw-r--r--src/designer/src/components/buddyeditor/buddyeditor_tool.h89
-rw-r--r--src/designer/src/components/component.pri2
-rw-r--r--src/designer/src/components/components.pro3
-rw-r--r--src/designer/src/components/formeditor/brushmanagerproxy.cpp303
-rw-r--r--src/designer/src/components/formeditor/brushmanagerproxy.h77
-rw-r--r--src/designer/src/components/formeditor/default_actionprovider.cpp207
-rw-r--r--src/designer/src/components/formeditor/default_actionprovider.h131
-rw-r--r--src/designer/src/components/formeditor/default_container.cpp173
-rw-r--r--src/designer/src/components/formeditor/default_container.h213
-rw-r--r--src/designer/src/components/formeditor/default_layoutdecoration.cpp79
-rw-r--r--src/designer/src/components/formeditor/default_layoutdecoration.h69
-rw-r--r--src/designer/src/components/formeditor/defaultbrushes.xml542
-rw-r--r--src/designer/src/components/formeditor/deviceprofiledialog.cpp203
-rw-r--r--src/designer/src/components/formeditor/deviceprofiledialog.h104
-rw-r--r--src/designer/src/components/formeditor/deviceprofiledialog.ui108
-rw-r--r--src/designer/src/components/formeditor/dpi_chooser.cpp207
-rw-r--r--src/designer/src/components/formeditor/dpi_chooser.h94
-rw-r--r--src/designer/src/components/formeditor/embeddedoptionspage.cpp453
-rw-r--r--src/designer/src/components/formeditor/embeddedoptionspage.h103
-rw-r--r--src/designer/src/components/formeditor/formeditor.cpp203
-rw-r--r--src/designer/src/components/formeditor/formeditor.h69
-rw-r--r--src/designer/src/components/formeditor/formeditor.pri77
-rw-r--r--src/designer/src/components/formeditor/formeditor.qrc175
-rw-r--r--src/designer/src/components/formeditor/formeditor_global.h57
-rw-r--r--src/designer/src/components/formeditor/formeditor_optionspage.cpp191
-rw-r--r--src/designer/src/components/formeditor/formeditor_optionspage.h79
-rw-r--r--src/designer/src/components/formeditor/formwindow.cpp2981
-rw-r--r--src/designer/src/components/formeditor/formwindow.h374
-rw-r--r--src/designer/src/components/formeditor/formwindow_dnditem.cpp116
-rw-r--r--src/designer/src/components/formeditor/formwindow_dnditem.h65
-rw-r--r--src/designer/src/components/formeditor/formwindow_widgetstack.cpp217
-rw-r--r--src/designer/src/components/formeditor/formwindow_widgetstack.h102
-rw-r--r--src/designer/src/components/formeditor/formwindowcursor.cpp211
-rw-r--r--src/designer/src/components/formeditor/formwindowcursor.h93
-rw-r--r--src/designer/src/components/formeditor/formwindowmanager.cpp1036
-rw-r--r--src/designer/src/components/formeditor/formwindowmanager.h200
-rw-r--r--src/designer/src/components/formeditor/formwindowsettings.cpp282
-rw-r--r--src/designer/src/components/formeditor/formwindowsettings.h85
-rw-r--r--src/designer/src/components/formeditor/formwindowsettings.ui328
-rw-r--r--src/designer/src/components/formeditor/iconcache.cpp121
-rw-r--r--src/designer/src/components/formeditor/iconcache.h78
-rw-r--r--src/designer/src/components/formeditor/images/cleartext.pngbin0 -> 760 bytes
-rw-r--r--src/designer/src/components/formeditor/images/color.pngbin0 -> 117 bytes
-rw-r--r--src/designer/src/components/formeditor/images/configure.pngbin0 -> 1016 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/arrow.pngbin0 -> 171 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/busy.pngbin0 -> 201 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/closedhand.pngbin0 -> 147 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/cross.pngbin0 -> 130 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/hand.pngbin0 -> 159 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/hsplit.pngbin0 -> 155 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/ibeam.pngbin0 -> 124 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/no.pngbin0 -> 199 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/openhand.pngbin0 -> 160 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/sizeall.pngbin0 -> 174 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/sizeb.pngbin0 -> 161 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/sizef.pngbin0 -> 161 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/sizeh.pngbin0 -> 145 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/sizev.pngbin0 -> 141 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/uparrow.pngbin0 -> 132 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/vsplit.pngbin0 -> 161 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/wait.pngbin0 -> 172 bytes
-rw-r--r--src/designer/src/components/formeditor/images/cursors/whatsthis.pngbin0 -> 191 bytes
-rw-r--r--src/designer/src/components/formeditor/images/downplus.pngbin0 -> 562 bytes
-rw-r--r--src/designer/src/components/formeditor/images/dropdownbutton.pngbin0 -> 527 bytes
-rw-r--r--src/designer/src/components/formeditor/images/edit.pngbin0 -> 929 bytes
-rw-r--r--src/designer/src/components/formeditor/images/editdelete-16.pngbin0 -> 553 bytes
-rw-r--r--src/designer/src/components/formeditor/images/emptyicon.pngbin0 -> 108 bytes
-rw-r--r--src/designer/src/components/formeditor/images/filenew-16.pngbin0 -> 454 bytes
-rw-r--r--src/designer/src/components/formeditor/images/fileopen-16.pngbin0 -> 549 bytes
-rw-r--r--src/designer/src/components/formeditor/images/leveldown.pngbin0 -> 557 bytes
-rw-r--r--src/designer/src/components/formeditor/images/levelup.pngbin0 -> 564 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/adjustsize.pngbin0 -> 1929 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/back.pngbin0 -> 678 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/buddytool.pngbin0 -> 2046 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/down.pngbin0 -> 594 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editbreaklayout.pngbin0 -> 2067 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editcut.pngbin0 -> 1512 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editdelete.pngbin0 -> 1097 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editform.pngbin0 -> 621 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editgrid.pngbin0 -> 751 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/edithlayout.pngbin0 -> 1395 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/edithlayoutsplit.pngbin0 -> 1188 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editlower.pngbin0 -> 595 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editpaste.pngbin0 -> 1906 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editraise.pngbin0 -> 1213 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editvlayout.pngbin0 -> 586 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/editvlayoutsplit.pngbin0 -> 872 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/filenew.pngbin0 -> 772 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/fileopen.pngbin0 -> 904 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/filesave.pngbin0 -> 1206 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/forward.pngbin0 -> 655 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/insertimage.pngbin0 -> 1280 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/minus.pngbin0 -> 488 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/plus.pngbin0 -> 810 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/redo.pngbin0 -> 1752 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/resetproperty.pngbin0 -> 169 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/resourceeditortool.pngbin0 -> 2171 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/signalslottool.pngbin0 -> 1989 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/simplifyrichtext.pngbin0 -> 1988 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/tabordertool.pngbin0 -> 1963 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textanchor.pngbin0 -> 2543 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textbold.pngbin0 -> 1611 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textcenter.pngbin0 -> 1404 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textitalic.pngbin0 -> 1164 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textjustify.pngbin0 -> 1257 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textleft.pngbin0 -> 1235 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textright.pngbin0 -> 1406 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textsubscript.pngbin0 -> 1054 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textsuperscript.pngbin0 -> 1109 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/textunder.pngbin0 -> 1183 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/undo.pngbin0 -> 1746 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/up.pngbin0 -> 692 bytes
-rw-r--r--src/designer/src/components/formeditor/images/mac/widgettool.pngbin0 -> 1874 bytes
-rw-r--r--src/designer/src/components/formeditor/images/minus-16.pngbin0 -> 296 bytes
-rw-r--r--src/designer/src/components/formeditor/images/plus-16.pngbin0 -> 383 bytes
-rw-r--r--src/designer/src/components/formeditor/images/prefix-add.pngbin0 -> 411 bytes
-rw-r--r--src/designer/src/components/formeditor/images/qt3logo.pngbin0 -> 1101 bytes
-rw-r--r--src/designer/src/components/formeditor/images/qtlogo.pngbin0 -> 825 bytes
-rw-r--r--src/designer/src/components/formeditor/images/reload.pngbin0 -> 1363 bytes
-rw-r--r--src/designer/src/components/formeditor/images/resetproperty.pngbin0 -> 169 bytes
-rw-r--r--src/designer/src/components/formeditor/images/sort.pngbin0 -> 563 bytes
-rw-r--r--src/designer/src/components/formeditor/images/submenu.pngbin0 -> 179 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/calendarwidget.pngbin0 -> 968 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/checkbox.pngbin0 -> 817 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/columnview.pngbin0 -> 518 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/combobox.pngbin0 -> 853 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/commandlinkbutton.pngbin0 -> 1208 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/dateedit.pngbin0 -> 672 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/datetimeedit.pngbin0 -> 1132 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/dial.pngbin0 -> 978 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/dialogbuttonbox.pngbin0 -> 1003 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/dockwidget.pngbin0 -> 638 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/doublespinbox.pngbin0 -> 749 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/fontcombobox.pngbin0 -> 966 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/frame.pngbin0 -> 721 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/graphicsview.pngbin0 -> 1182 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/groupbox.pngbin0 -> 439 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/groupboxcollapsible.pngbin0 -> 702 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/hscrollbar.pngbin0 -> 408 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/hslider.pngbin0 -> 729 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/hsplit.pngbin0 -> 164 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/label.pngbin0 -> 953 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/lcdnumber.pngbin0 -> 555 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/line.pngbin0 -> 287 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/lineedit.pngbin0 -> 405 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/listbox.pngbin0 -> 797 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/listview.pngbin0 -> 756 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/mdiarea.pngbin0 -> 643 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/plaintextedit.pngbin0 -> 807 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/progress.pngbin0 -> 559 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/pushbutton.pngbin0 -> 408 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/radiobutton.pngbin0 -> 586 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/scrollarea.pngbin0 -> 548 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/spacer.pngbin0 -> 686 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/spinbox.pngbin0 -> 680 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/tabbar.pngbin0 -> 623 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/table.pngbin0 -> 483 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/tabwidget.pngbin0 -> 572 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/textedit.pngbin0 -> 823 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/timeedit.pngbin0 -> 1353 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/toolbox.pngbin0 -> 783 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/toolbutton.pngbin0 -> 1167 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/vline.pngbin0 -> 314 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/vscrollbar.pngbin0 -> 415 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/vslider.pngbin0 -> 726 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/vspacer.pngbin0 -> 677 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/widget.pngbin0 -> 716 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/widgetstack.pngbin0 -> 828 bytes
-rw-r--r--src/designer/src/components/formeditor/images/widgets/wizard.pngbin0 -> 898 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/adjustsize.pngbin0 -> 1262 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/back.pngbin0 -> 678 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/buddytool.pngbin0 -> 997 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/down.pngbin0 -> 594 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editbreaklayout.pngbin0 -> 1321 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editcut.pngbin0 -> 1384 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editdelete.pngbin0 -> 850 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editform.pngbin0 -> 349 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editgrid.pngbin0 -> 349 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/edithlayout.pngbin0 -> 455 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/edithlayoutsplit.pngbin0 -> 860 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editlower.pngbin0 -> 1038 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editpaste.pngbin0 -> 1482 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editraise.pngbin0 -> 1045 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editvlayout.pngbin0 -> 340 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/editvlayoutsplit.pngbin0 -> 740 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/filenew.pngbin0 -> 768 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/fileopen.pngbin0 -> 1662 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/filesave.pngbin0 -> 1205 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/forward.pngbin0 -> 655 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/insertimage.pngbin0 -> 885 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/minus.pngbin0 -> 429 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/plus.pngbin0 -> 709 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/redo.pngbin0 -> 1212 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/resourceeditortool.pngbin0 -> 1429 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/signalslottool.pngbin0 -> 1128 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/simplifyrichtext.pngbin0 -> 1933 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/tabordertool.pngbin0 -> 1205 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textanchor.pngbin0 -> 1581 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textbold.pngbin0 -> 1134 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textcenter.pngbin0 -> 627 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textitalic.pngbin0 -> 829 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textjustify.pngbin0 -> 695 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textleft.pngbin0 -> 673 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textright.pngbin0 -> 677 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textsubscript.pngbin0 -> 897 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textsuperscript.pngbin0 -> 864 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/textunder.pngbin0 -> 971 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/undo.pngbin0 -> 1181 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/up.pngbin0 -> 692 bytes
-rw-r--r--src/designer/src/components/formeditor/images/win/widgettool.pngbin0 -> 1039 bytes
-rw-r--r--src/designer/src/components/formeditor/itemview_propertysheet.cpp270
-rw-r--r--src/designer/src/components/formeditor/itemview_propertysheet.h92
-rw-r--r--src/designer/src/components/formeditor/layout_propertysheet.cpp546
-rw-r--r--src/designer/src/components/formeditor/layout_propertysheet.h82
-rw-r--r--src/designer/src/components/formeditor/line_propertysheet.cpp86
-rw-r--r--src/designer/src/components/formeditor/line_propertysheet.h71
-rw-r--r--src/designer/src/components/formeditor/previewactiongroup.cpp149
-rw-r--r--src/designer/src/components/formeditor/previewactiongroup.h90
-rw-r--r--src/designer/src/components/formeditor/qdesigner_resource.cpp2475
-rw-r--r--src/designer/src/components/formeditor/qdesigner_resource.h178
-rw-r--r--src/designer/src/components/formeditor/qdesignerundostack.cpp112
-rw-r--r--src/designer/src/components/formeditor/qdesignerundostack.h90
-rw-r--r--src/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp83
-rw-r--r--src/designer/src/components/formeditor/qlayoutwidget_propertysheet.h72
-rw-r--r--src/designer/src/components/formeditor/qmainwindow_container.cpp199
-rw-r--r--src/designer/src/components/formeditor/qmainwindow_container.h81
-rw-r--r--src/designer/src/components/formeditor/qmdiarea_container.cpp281
-rw-r--r--src/designer/src/components/formeditor/qmdiarea_container.h119
-rw-r--r--src/designer/src/components/formeditor/qtbrushmanager.cpp140
-rw-r--r--src/designer/src/components/formeditor/qtbrushmanager.h85
-rw-r--r--src/designer/src/components/formeditor/qwizard_container.cpp226
-rw-r--r--src/designer/src/components/formeditor/qwizard_container.h123
-rw-r--r--src/designer/src/components/formeditor/qworkspace_container.cpp100
-rw-r--r--src/designer/src/components/formeditor/qworkspace_container.h79
-rw-r--r--src/designer/src/components/formeditor/spacer_propertysheet.cpp82
-rw-r--r--src/designer/src/components/formeditor/spacer_propertysheet.h72
-rw-r--r--src/designer/src/components/formeditor/templateoptionspage.cpp183
-rw-r--r--src/designer/src/components/formeditor/templateoptionspage.h110
-rw-r--r--src/designer/src/components/formeditor/templateoptionspage.ui59
-rw-r--r--src/designer/src/components/formeditor/tool_widgeteditor.cpp363
-rw-r--r--src/designer/src/components/formeditor/tool_widgeteditor.h107
-rw-r--r--src/designer/src/components/formeditor/widgetselection.cpp746
-rw-r--r--src/designer/src/components/formeditor/widgetselection.h145
-rw-r--r--src/designer/src/components/lib/lib.pro77
-rw-r--r--src/designer/src/components/lib/lib_pch.h43
-rw-r--r--src/designer/src/components/lib/qdesigner_components.cpp277
-rw-r--r--src/designer/src/components/objectinspector/objectinspector.cpp835
-rw-r--r--src/designer/src/components/objectinspector/objectinspector.h95
-rw-r--r--src/designer/src/components/objectinspector/objectinspector.pri16
-rw-r--r--src/designer/src/components/objectinspector/objectinspector_global.h61
-rw-r--r--src/designer/src/components/objectinspector/objectinspectormodel.cpp516
-rw-r--r--src/designer/src/components/objectinspector/objectinspectormodel_p.h168
-rw-r--r--src/designer/src/components/propertyeditor/brushpropertymanager.cpp298
-rw-r--r--src/designer/src/components/propertyeditor/brushpropertymanager.h105
-rw-r--r--src/designer/src/components/propertyeditor/designerpropertymanager.cpp2836
-rw-r--r--src/designer/src/components/propertyeditor/designerpropertymanager.h315
-rw-r--r--src/designer/src/components/propertyeditor/fontmapping.xml73
-rw-r--r--src/designer/src/components/propertyeditor/fontpropertymanager.cpp377
-rw-r--r--src/designer/src/components/propertyeditor/fontpropertymanager.h124
-rw-r--r--src/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp170
-rw-r--r--src/designer/src/components/propertyeditor/newdynamicpropertydialog.h104
-rw-r--r--src/designer/src/components/propertyeditor/newdynamicpropertydialog.ui106
-rw-r--r--src/designer/src/components/propertyeditor/paletteeditor.cpp616
-rw-r--r--src/designer/src/components/propertyeditor/paletteeditor.h204
-rw-r--r--src/designer/src/components/propertyeditor/paletteeditor.ui264
-rw-r--r--src/designer/src/components/propertyeditor/paletteeditorbutton.cpp88
-rw-r--r--src/designer/src/components/propertyeditor/paletteeditorbutton.h86
-rw-r--r--src/designer/src/components/propertyeditor/previewframe.cpp119
-rw-r--r--src/designer/src/components/propertyeditor/previewframe.h76
-rw-r--r--src/designer/src/components/propertyeditor/previewwidget.cpp59
-rw-r--r--src/designer/src/components/propertyeditor/previewwidget.h66
-rw-r--r--src/designer/src/components/propertyeditor/previewwidget.ui238
-rw-r--r--src/designer/src/components/propertyeditor/propertyeditor.cpp1294
-rw-r--r--src/designer/src/components/propertyeditor/propertyeditor.h207
-rw-r--r--src/designer/src/components/propertyeditor/propertyeditor.pri52
-rw-r--r--src/designer/src/components/propertyeditor/propertyeditor.qrc5
-rw-r--r--src/designer/src/components/propertyeditor/propertyeditor_global.h61
-rw-r--r--src/designer/src/components/propertyeditor/qlonglongvalidator.cpp153
-rw-r--r--src/designer/src/components/propertyeditor/qlonglongvalidator.h110
-rw-r--r--src/designer/src/components/propertyeditor/stringlisteditor.cpp212
-rw-r--r--src/designer/src/components/propertyeditor/stringlisteditor.h92
-rw-r--r--src/designer/src/components/propertyeditor/stringlisteditor.ui265
-rw-r--r--src/designer/src/components/propertyeditor/stringlisteditorbutton.cpp81
-rw-r--r--src/designer/src/components/propertyeditor/stringlisteditorbutton.h81
-rw-r--r--src/designer/src/components/signalsloteditor/connectdialog.cpp335
-rw-r--r--src/designer/src/components/signalsloteditor/connectdialog.ui150
-rw-r--r--src/designer/src/components/signalsloteditor/connectdialog_p.h109
-rw-r--r--src/designer/src/components/signalsloteditor/signalslot_utils.cpp334
-rw-r--r--src/designer/src/components/signalsloteditor/signalslot_utils_p.h104
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor.cpp528
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor.h98
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor.pri21
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_global.h57
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp50
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_p.h138
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp133
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_plugin.h92
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp123
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditor_tool.h93
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp864
-rw-r--r--src/designer/src/components/signalsloteditor/signalsloteditorwindow.h96
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor.cpp433
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor.h109
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor.pri16
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_global.h57
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_instance.cpp49
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_plugin.cpp133
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_plugin.h93
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_tool.cpp114
-rw-r--r--src/designer/src/components/tabordereditor/tabordereditor_tool.h89
-rw-r--r--src/designer/src/components/taskmenu/button_taskmenu.cpp709
-rw-r--r--src/designer/src/components/taskmenu/button_taskmenu.h170
-rw-r--r--src/designer/src/components/taskmenu/combobox_taskmenu.cpp133
-rw-r--r--src/designer/src/components/taskmenu/combobox_taskmenu.h94
-rw-r--r--src/designer/src/components/taskmenu/containerwidget_taskmenu.cpp348
-rw-r--r--src/designer/src/components/taskmenu/containerwidget_taskmenu.h157
-rw-r--r--src/designer/src/components/taskmenu/groupbox_taskmenu.cpp105
-rw-r--r--src/designer/src/components/taskmenu/groupbox_taskmenu.h77
-rw-r--r--src/designer/src/components/taskmenu/inplace_editor.cpp136
-rw-r--r--src/designer/src/components/taskmenu/inplace_editor.h110
-rw-r--r--src/designer/src/components/taskmenu/inplace_widget_helper.cpp120
-rw-r--r--src/designer/src/components/taskmenu/inplace_widget_helper.h88
-rw-r--r--src/designer/src/components/taskmenu/itemlisteditor.cpp478
-rw-r--r--src/designer/src/components/taskmenu/itemlisteditor.h165
-rw-r--r--src/designer/src/components/taskmenu/itemlisteditor.ui156
-rw-r--r--src/designer/src/components/taskmenu/label_taskmenu.cpp117
-rw-r--r--src/designer/src/components/taskmenu/label_taskmenu.h81
-rw-r--r--src/designer/src/components/taskmenu/layouttaskmenu.cpp93
-rw-r--r--src/designer/src/components/taskmenu/layouttaskmenu.h93
-rw-r--r--src/designer/src/components/taskmenu/lineedit_taskmenu.cpp103
-rw-r--r--src/designer/src/components/taskmenu/lineedit_taskmenu.h74
-rw-r--r--src/designer/src/components/taskmenu/listwidget_taskmenu.cpp117
-rw-r--r--src/designer/src/components/taskmenu/listwidget_taskmenu.h85
-rw-r--r--src/designer/src/components/taskmenu/listwidgeteditor.cpp138
-rw-r--r--src/designer/src/components/taskmenu/listwidgeteditor.h78
-rw-r--r--src/designer/src/components/taskmenu/menutaskmenu.cpp107
-rw-r--r--src/designer/src/components/taskmenu/menutaskmenu.h106
-rw-r--r--src/designer/src/components/taskmenu/tablewidget_taskmenu.cpp115
-rw-r--r--src/designer/src/components/taskmenu/tablewidget_taskmenu.h85
-rw-r--r--src/designer/src/components/taskmenu/tablewidgeteditor.cpp450
-rw-r--r--src/designer/src/components/taskmenu/tablewidgeteditor.h130
-rw-r--r--src/designer/src/components/taskmenu/tablewidgeteditor.ui157
-rw-r--r--src/designer/src/components/taskmenu/taskmenu.pri50
-rw-r--r--src/designer/src/components/taskmenu/taskmenu_component.cpp106
-rw-r--r--src/designer/src/components/taskmenu/taskmenu_component.h73
-rw-r--r--src/designer/src/components/taskmenu/taskmenu_global.h57
-rw-r--r--src/designer/src/components/taskmenu/textedit_taskmenu.cpp105
-rw-r--r--src/designer/src/components/taskmenu/textedit_taskmenu.h89
-rw-r--r--src/designer/src/components/taskmenu/toolbar_taskmenu.cpp111
-rw-r--r--src/designer/src/components/taskmenu/toolbar_taskmenu.h99
-rw-r--r--src/designer/src/components/taskmenu/treewidget_taskmenu.cpp114
-rw-r--r--src/designer/src/components/taskmenu/treewidget_taskmenu.h85
-rw-r--r--src/designer/src/components/taskmenu/treewidgeteditor.cpp642
-rw-r--r--src/designer/src/components/taskmenu/treewidgeteditor.h129
-rw-r--r--src/designer/src/components/taskmenu/treewidgeteditor.ui257
-rw-r--r--src/designer/src/components/widgetbox/widgetbox.cpp235
-rw-r--r--src/designer/src/components/widgetbox/widgetbox.h103
-rw-r--r--src/designer/src/components/widgetbox/widgetbox.pri14
-rw-r--r--src/designer/src/components/widgetbox/widgetbox.qrc5
-rw-r--r--src/designer/src/components/widgetbox/widgetbox.xml932
-rw-r--r--src/designer/src/components/widgetbox/widgetbox_dnditem.cpp225
-rw-r--r--src/designer/src/components/widgetbox/widgetbox_dnditem.h67
-rw-r--r--src/designer/src/components/widgetbox/widgetbox_global.h57
-rw-r--r--src/designer/src/components/widgetbox/widgetboxcategorylistview.cpp510
-rw-r--r--src/designer/src/components/widgetbox/widgetboxcategorylistview.h118
-rw-r--r--src/designer/src/components/widgetbox/widgetboxtreewidget.cpp1001
-rw-r--r--src/designer/src/components/widgetbox/widgetboxtreewidget.h150
-rw-r--r--src/designer/src/designer/Info_mac.plist35
-rw-r--r--src/designer/src/designer/appfontdialog.cpp429
-rw-r--r--src/designer/src/designer/appfontdialog.h101
-rw-r--r--src/designer/src/designer/assistantclient.cpp175
-rw-r--r--src/designer/src/designer/assistantclient.h83
-rw-r--r--src/designer/src/designer/designer.icnsbin0 -> 154893 bytes
-rw-r--r--src/designer/src/designer/designer.icobin0 -> 355574 bytes
-rw-r--r--src/designer/src/designer/designer.pro90
-rw-r--r--src/designer/src/designer/designer.qrc5
-rw-r--r--src/designer/src/designer/designer.rc32
-rw-r--r--src/designer/src/designer/designer_enums.h52
-rw-r--r--src/designer/src/designer/images/designer.pngbin0 -> 4205 bytes
-rw-r--r--src/designer/src/designer/images/mdi.pngbin0 -> 59505 bytes
-rw-r--r--src/designer/src/designer/images/sdi.pngbin0 -> 61037 bytes
-rw-r--r--src/designer/src/designer/images/workbench.pngbin0 -> 2085 bytes
-rw-r--r--src/designer/src/designer/main.cpp58
-rw-r--r--src/designer/src/designer/mainwindow.cpp419
-rw-r--r--src/designer/src/designer/mainwindow.h187
-rw-r--r--src/designer/src/designer/newform.cpp227
-rw-r--r--src/designer/src/designer/newform.h104
-rw-r--r--src/designer/src/designer/preferencesdialog.cpp118
-rw-r--r--src/designer/src/designer/preferencesdialog.h82
-rw-r--r--src/designer/src/designer/preferencesdialog.ui91
-rw-r--r--src/designer/src/designer/qdesigner.cpp320
-rw-r--r--src/designer/src/designer/qdesigner.h102
-rw-r--r--src/designer/src/designer/qdesigner_actions.cpp1437
-rw-r--r--src/designer/src/designer/qdesigner_actions.h231
-rw-r--r--src/designer/src/designer/qdesigner_appearanceoptions.cpp167
-rw-r--r--src/designer/src/designer/qdesigner_appearanceoptions.h136
-rw-r--r--src/designer/src/designer/qdesigner_appearanceoptions.ui57
-rw-r--r--src/designer/src/designer/qdesigner_formwindow.cpp290
-rw-r--r--src/designer/src/designer/qdesigner_formwindow.h97
-rw-r--r--src/designer/src/designer/qdesigner_pch.h59
-rw-r--r--src/designer/src/designer/qdesigner_server.cpp156
-rw-r--r--src/designer/src/designer/qdesigner_server.h89
-rw-r--r--src/designer/src/designer/qdesigner_settings.cpp250
-rw-r--r--src/designer/src/designer/qdesigner_settings.h94
-rw-r--r--src/designer/src/designer/qdesigner_toolwindow.cpp438
-rw-r--r--src/designer/src/designer/qdesigner_toolwindow.h123
-rw-r--r--src/designer/src/designer/qdesigner_workbench.cpp1100
-rw-r--r--src/designer/src/designer/qdesigner_workbench.h215
-rw-r--r--src/designer/src/designer/saveformastemplate.cpp173
-rw-r--r--src/designer/src/designer/saveformastemplate.h77
-rw-r--r--src/designer/src/designer/saveformastemplate.ui166
-rw-r--r--src/designer/src/designer/uifile.icnsbin0 -> 123696 bytes
-rw-r--r--src/designer/src/designer/versiondialog.cpp191
-rw-r--r--src/designer/src/designer/versiondialog.h58
-rw-r--r--src/designer/src/lib/components/qdesigner_components.h82
-rw-r--r--src/designer/src/lib/components/qdesigner_components_global.h66
-rw-r--r--src/designer/src/lib/extension/default_extensionfactory.cpp178
-rw-r--r--src/designer/src/lib/extension/default_extensionfactory.h86
-rw-r--r--src/designer/src/lib/extension/extension.cpp186
-rw-r--r--src/designer/src/lib/extension/extension.h109
-rw-r--r--src/designer/src/lib/extension/extension.pri12
-rw-r--r--src/designer/src/lib/extension/extension_global.h64
-rw-r--r--src/designer/src/lib/extension/qextensionmanager.cpp174
-rw-r--r--src/designer/src/lib/extension/qextensionmanager.h79
-rw-r--r--src/designer/src/lib/lib.pro78
-rw-r--r--src/designer/src/lib/lib_pch.h65
-rw-r--r--src/designer/src/lib/sdk/abstractactioneditor.cpp123
-rw-r--r--src/designer/src/lib/sdk/abstractactioneditor.h76
-rw-r--r--src/designer/src/lib/sdk/abstractbrushmanager.h83
-rw-r--r--src/designer/src/lib/sdk/abstractdialoggui.cpp161
-rw-r--r--src/designer/src/lib/sdk/abstractdialoggui_p.h107
-rw-r--r--src/designer/src/lib/sdk/abstractdnditem.h75
-rw-r--r--src/designer/src/lib/sdk/abstractdnditem.qdoc98
-rw-r--r--src/designer/src/lib/sdk/abstractformeditor.cpp630
-rw-r--r--src/designer/src/lib/sdk/abstractformeditor.h159
-rw-r--r--src/designer/src/lib/sdk/abstractformeditorplugin.cpp86
-rw-r--r--src/designer/src/lib/sdk/abstractformeditorplugin.h73
-rw-r--r--src/designer/src/lib/sdk/abstractformwindow.cpp814
-rw-r--r--src/designer/src/lib/sdk/abstractformwindow.h183
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowcursor.cpp252
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowcursor.h109
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowmanager.cpp502
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowmanager.h122
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowtool.cpp106
-rw-r--r--src/designer/src/lib/sdk/abstractformwindowtool.h85
-rw-r--r--src/designer/src/lib/sdk/abstracticoncache.h83
-rw-r--r--src/designer/src/lib/sdk/abstracticoncache.qdoc116
-rw-r--r--src/designer/src/lib/sdk/abstractintegration.cpp105
-rw-r--r--src/designer/src/lib/sdk/abstractintegration.h86
-rw-r--r--src/designer/src/lib/sdk/abstractintrospection.cpp548
-rw-r--r--src/designer/src/lib/sdk/abstractintrospection_p.h174
-rw-r--r--src/designer/src/lib/sdk/abstractlanguage.h100
-rw-r--r--src/designer/src/lib/sdk/abstractmetadatabase.cpp170
-rw-r--r--src/designer/src/lib/sdk/abstractmetadatabase.h99
-rw-r--r--src/designer/src/lib/sdk/abstractnewformwidget.cpp117
-rw-r--r--src/designer/src/lib/sdk/abstractnewformwidget_p.h88
-rw-r--r--src/designer/src/lib/sdk/abstractobjectinspector.cpp110
-rw-r--r--src/designer/src/lib/sdk/abstractobjectinspector.h73
-rw-r--r--src/designer/src/lib/sdk/abstractoptionspage_p.h79
-rw-r--r--src/designer/src/lib/sdk/abstractpromotioninterface.cpp113
-rw-r--r--src/designer/src/lib/sdk/abstractpromotioninterface.h91
-rw-r--r--src/designer/src/lib/sdk/abstractpropertyeditor.cpp193
-rw-r--r--src/designer/src/lib/sdk/abstractpropertyeditor.h84
-rw-r--r--src/designer/src/lib/sdk/abstractresourcebrowser.cpp57
-rw-r--r--src/designer/src/lib/sdk/abstractresourcebrowser.h75
-rw-r--r--src/designer/src/lib/sdk/abstractsettings_p.h87
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetbox.cpp340
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetbox.h142
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetdatabase.cpp360
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetdatabase.h137
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetfactory.cpp112
-rw-r--r--src/designer/src/lib/sdk/abstractwidgetfactory.h79
-rw-r--r--src/designer/src/lib/sdk/dynamicpropertysheet.h81
-rw-r--r--src/designer/src/lib/sdk/dynamicpropertysheet.qdoc80
-rw-r--r--src/designer/src/lib/sdk/extrainfo.cpp116
-rw-r--r--src/designer/src/lib/sdk/extrainfo.h84
-rw-r--r--src/designer/src/lib/sdk/layoutdecoration.h99
-rw-r--r--src/designer/src/lib/sdk/layoutdecoration.qdoc149
-rw-r--r--src/designer/src/lib/sdk/membersheet.h89
-rw-r--r--src/designer/src/lib/sdk/membersheet.qdoc249
-rw-r--r--src/designer/src/lib/sdk/propertysheet.h90
-rw-r--r--src/designer/src/lib/sdk/propertysheet.qdoc288
-rw-r--r--src/designer/src/lib/sdk/script.cpp109
-rw-r--r--src/designer/src/lib/sdk/script_p.h83
-rw-r--r--src/designer/src/lib/sdk/sdk.pri58
-rw-r--r--src/designer/src/lib/sdk/sdk_global.h64
-rw-r--r--src/designer/src/lib/sdk/taskmenu.h72
-rw-r--r--src/designer/src/lib/sdk/taskmenu.qdoc138
-rw-r--r--src/designer/src/lib/shared/actioneditor.cpp823
-rw-r--r--src/designer/src/lib/shared/actioneditor_p.h168
-rw-r--r--src/designer/src/lib/shared/actionprovider_p.h108
-rw-r--r--src/designer/src/lib/shared/actionrepository.cpp665
-rw-r--r--src/designer/src/lib/shared/actionrepository_p.h269
-rw-r--r--src/designer/src/lib/shared/addlinkdialog.ui112
-rw-r--r--src/designer/src/lib/shared/codedialog.cpp262
-rw-r--r--src/designer/src/lib/shared/codedialog_p.h100
-rw-r--r--src/designer/src/lib/shared/connectionedit.cpp1612
-rw-r--r--src/designer/src/lib/shared/connectionedit_p.h324
-rw-r--r--src/designer/src/lib/shared/csshighlighter.cpp188
-rw-r--r--src/designer/src/lib/shared/csshighlighter_p.h82
-rw-r--r--src/designer/src/lib/shared/defaultgradients.xml498
-rw-r--r--src/designer/src/lib/shared/deviceprofile.cpp467
-rw-r--r--src/designer/src/lib/shared/deviceprofile_p.h152
-rw-r--r--src/designer/src/lib/shared/dialoggui.cpp265
-rw-r--r--src/designer/src/lib/shared/dialoggui_p.h107
-rw-r--r--src/designer/src/lib/shared/extensionfactory_p.h120
-rw-r--r--src/designer/src/lib/shared/filterwidget.cpp252
-rw-r--r--src/designer/src/lib/shared/filterwidget_p.h151
-rw-r--r--src/designer/src/lib/shared/formlayoutmenu.cpp534
-rw-r--r--src/designer/src/lib/shared/formlayoutmenu_p.h100
-rw-r--r--src/designer/src/lib/shared/formlayoutrowdialog.ui166
-rw-r--r--src/designer/src/lib/shared/formwindowbase.cpp502
-rw-r--r--src/designer/src/lib/shared/formwindowbase_p.h205
-rw-r--r--src/designer/src/lib/shared/grid.cpp194
-rw-r--r--src/designer/src/lib/shared/grid_p.h118
-rw-r--r--src/designer/src/lib/shared/gridpanel.cpp121
-rw-r--r--src/designer/src/lib/shared/gridpanel.ui144
-rw-r--r--src/designer/src/lib/shared/gridpanel_p.h101
-rw-r--r--src/designer/src/lib/shared/htmlhighlighter.cpp198
-rw-r--r--src/designer/src/lib/shared/htmlhighlighter_p.h101
-rw-r--r--src/designer/src/lib/shared/iconloader.cpp79
-rw-r--r--src/designer/src/lib/shared/iconloader_p.h72
-rw-r--r--src/designer/src/lib/shared/iconselector.cpp655
-rw-r--r--src/designer/src/lib/shared/iconselector_p.h172
-rw-r--r--src/designer/src/lib/shared/invisible_widget.cpp57
-rw-r--r--src/designer/src/lib/shared/invisible_widget_p.h75
-rw-r--r--src/designer/src/lib/shared/layout.cpp1332
-rw-r--r--src/designer/src/lib/shared/layout_p.h152
-rw-r--r--src/designer/src/lib/shared/layoutinfo.cpp312
-rw-r--r--src/designer/src/lib/shared/layoutinfo_p.h114
-rw-r--r--src/designer/src/lib/shared/metadatabase.cpp295
-rw-r--r--src/designer/src/lib/shared/metadatabase_p.h142
-rw-r--r--src/designer/src/lib/shared/morphmenu.cpp635
-rw-r--r--src/designer/src/lib/shared/morphmenu_p.h97
-rw-r--r--src/designer/src/lib/shared/newactiondialog.cpp199
-rw-r--r--src/designer/src/lib/shared/newactiondialog.ui313
-rw-r--r--src/designer/src/lib/shared/newactiondialog_p.h124
-rw-r--r--src/designer/src/lib/shared/newformwidget.cpp586
-rw-r--r--src/designer/src/lib/shared/newformwidget.ui192
-rw-r--r--src/designer/src/lib/shared/newformwidget_p.h143
-rw-r--r--src/designer/src/lib/shared/orderdialog.cpp188
-rw-r--r--src/designer/src/lib/shared/orderdialog.ui198
-rw-r--r--src/designer/src/lib/shared/orderdialog_p.h114
-rw-r--r--src/designer/src/lib/shared/plaintexteditor.cpp119
-rw-r--r--src/designer/src/lib/shared/plaintexteditor_p.h89
-rw-r--r--src/designer/src/lib/shared/plugindialog.cpp207
-rw-r--r--src/designer/src/lib/shared/plugindialog.ui136
-rw-r--r--src/designer/src/lib/shared/plugindialog_p.h92
-rw-r--r--src/designer/src/lib/shared/pluginmanager.cpp786
-rw-r--r--src/designer/src/lib/shared/pluginmanager_p.h159
-rw-r--r--src/designer/src/lib/shared/previewconfigurationwidget.cpp366
-rw-r--r--src/designer/src/lib/shared/previewconfigurationwidget.ui91
-rw-r--r--src/designer/src/lib/shared/previewconfigurationwidget_p.h96
-rw-r--r--src/designer/src/lib/shared/previewmanager.cpp943
-rw-r--r--src/designer/src/lib/shared/previewmanager_p.h184
-rw-r--r--src/designer/src/lib/shared/promotionmodel.cpp220
-rw-r--r--src/designer/src/lib/shared/promotionmodel_p.h98
-rw-r--r--src/designer/src/lib/shared/promotiontaskmenu.cpp361
-rw-r--r--src/designer/src/lib/shared/promotiontaskmenu_p.h151
-rw-r--r--src/designer/src/lib/shared/propertylineedit.cpp96
-rw-r--r--src/designer/src/lib/shared/propertylineedit_p.h85
-rw-r--r--src/designer/src/lib/shared/qdesigner_command.cpp2968
-rw-r--r--src/designer/src/lib/shared/qdesigner_command2.cpp221
-rw-r--r--src/designer/src/lib/shared/qdesigner_command2_p.h123
-rw-r--r--src/designer/src/lib/shared/qdesigner_command_p.h1136
-rw-r--r--src/designer/src/lib/shared/qdesigner_dnditem.cpp300
-rw-r--r--src/designer/src/lib/shared/qdesigner_dnditem_p.h147
-rw-r--r--src/designer/src/lib/shared/qdesigner_dockwidget.cpp140
-rw-r--r--src/designer/src/lib/shared/qdesigner_dockwidget_p.h87
-rw-r--r--src/designer/src/lib/shared/qdesigner_formbuilder.cpp498
-rw-r--r--src/designer/src/lib/shared/qdesigner_formbuilder_p.h181
-rw-r--r--src/designer/src/lib/shared/qdesigner_formeditorcommand.cpp64
-rw-r--r--src/designer/src/lib/shared/qdesigner_formeditorcommand_p.h83
-rw-r--r--src/designer/src/lib/shared/qdesigner_formwindowcommand.cpp151
-rw-r--r--src/designer/src/lib/shared/qdesigner_formwindowcommand_p.h98
-rw-r--r--src/designer/src/lib/shared/qdesigner_formwindowmanager.cpp167
-rw-r--r--src/designer/src/lib/shared/qdesigner_formwindowmanager_p.h99
-rw-r--r--src/designer/src/lib/shared/qdesigner_integration.cpp496
-rw-r--r--src/designer/src/lib/shared/qdesigner_integration_p.h152
-rw-r--r--src/designer/src/lib/shared/qdesigner_introspection.cpp372
-rw-r--r--src/designer/src/lib/shared/qdesigner_introspection_p.h84
-rw-r--r--src/designer/src/lib/shared/qdesigner_membersheet.cpp371
-rw-r--r--src/designer/src/lib/shared/qdesigner_membersheet_p.h120
-rw-r--r--src/designer/src/lib/shared/qdesigner_menu.cpp1390
-rw-r--r--src/designer/src/lib/shared/qdesigner_menu_p.h208
-rw-r--r--src/designer/src/lib/shared/qdesigner_menubar.cpp979
-rw-r--r--src/designer/src/lib/shared/qdesigner_menubar_p.h179
-rw-r--r--src/designer/src/lib/shared/qdesigner_objectinspector.cpp80
-rw-r--r--src/designer/src/lib/shared/qdesigner_objectinspector_p.h103
-rw-r--r--src/designer/src/lib/shared/qdesigner_promotion.cpp373
-rw-r--r--src/designer/src/lib/shared/qdesigner_promotion_p.h98
-rw-r--r--src/designer/src/lib/shared/qdesigner_promotiondialog.cpp456
-rw-r--r--src/designer/src/lib/shared/qdesigner_promotiondialog_p.h170
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertycommand.cpp1503
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertycommand_p.h313
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertyeditor.cpp169
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertyeditor_p.h112
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertysheet.cpp1657
-rw-r--r--src/designer/src/lib/shared/qdesigner_propertysheet_p.h266
-rw-r--r--src/designer/src/lib/shared/qdesigner_qsettings.cpp94
-rw-r--r--src/designer/src/lib/shared/qdesigner_qsettings_p.h88
-rw-r--r--src/designer/src/lib/shared/qdesigner_stackedbox.cpp399
-rw-r--r--src/designer/src/lib/shared/qdesigner_stackedbox_p.h164
-rw-r--r--src/designer/src/lib/shared/qdesigner_tabwidget.cpp572
-rw-r--r--src/designer/src/lib/shared/qdesigner_tabwidget_p.h153
-rw-r--r--src/designer/src/lib/shared/qdesigner_taskmenu.cpp912
-rw-r--r--src/designer/src/lib/shared/qdesigner_taskmenu_p.h133
-rw-r--r--src/designer/src/lib/shared/qdesigner_toolbar.cpp488
-rw-r--r--src/designer/src/lib/shared/qdesigner_toolbar_p.h135
-rw-r--r--src/designer/src/lib/shared/qdesigner_toolbox.cpp437
-rw-r--r--src/designer/src/lib/shared/qdesigner_toolbox_p.h140
-rw-r--r--src/designer/src/lib/shared/qdesigner_utils.cpp848
-rw-r--r--src/designer/src/lib/shared/qdesigner_utils_p.h499
-rw-r--r--src/designer/src/lib/shared/qdesigner_widget.cpp108
-rw-r--r--src/designer/src/lib/shared/qdesigner_widget_p.h122
-rw-r--r--src/designer/src/lib/shared/qdesigner_widgetbox.cpp181
-rw-r--r--src/designer/src/lib/shared/qdesigner_widgetbox_p.h101
-rw-r--r--src/designer/src/lib/shared/qdesigner_widgetitem.cpp345
-rw-r--r--src/designer/src/lib/shared/qdesigner_widgetitem_p.h147
-rw-r--r--src/designer/src/lib/shared/qlayout_widget.cpp2107
-rw-r--r--src/designer/src/lib/shared/qlayout_widget_p.h292
-rw-r--r--src/designer/src/lib/shared/qscripthighlighter.cpp468
-rw-r--r--src/designer/src/lib/shared/qscripthighlighter_p.h84
-rw-r--r--src/designer/src/lib/shared/qsimpleresource.cpp418
-rw-r--r--src/designer/src/lib/shared/qsimpleresource_p.h164
-rw-r--r--src/designer/src/lib/shared/qtresourceeditordialog.cpp2223
-rw-r--r--src/designer/src/lib/shared/qtresourceeditordialog.ui177
-rw-r--r--src/designer/src/lib/shared/qtresourceeditordialog_p.h130
-rw-r--r--src/designer/src/lib/shared/qtresourcemodel.cpp650
-rw-r--r--src/designer/src/lib/shared/qtresourcemodel_p.h145
-rw-r--r--src/designer/src/lib/shared/qtresourceview.cpp906
-rw-r--r--src/designer/src/lib/shared/qtresourceview_p.h141
-rw-r--r--src/designer/src/lib/shared/richtexteditor.cpp906
-rw-r--r--src/designer/src/lib/shared/richtexteditor_p.h103
-rw-r--r--src/designer/src/lib/shared/scriptcommand.cpp103
-rw-r--r--src/designer/src/lib/shared/scriptcommand_p.h93
-rw-r--r--src/designer/src/lib/shared/scriptdialog.cpp130
-rw-r--r--src/designer/src/lib/shared/scriptdialog_p.h90
-rw-r--r--src/designer/src/lib/shared/scripterrordialog.cpp108
-rw-r--r--src/designer/src/lib/shared/scripterrordialog_p.h83
-rw-r--r--src/designer/src/lib/shared/selectsignaldialog.ui93
-rw-r--r--src/designer/src/lib/shared/shared.pri189
-rw-r--r--src/designer/src/lib/shared/shared.qrc20
-rw-r--r--src/designer/src/lib/shared/shared_enums_p.h99
-rw-r--r--src/designer/src/lib/shared/shared_global_p.h76
-rw-r--r--src/designer/src/lib/shared/shared_settings.cpp321
-rw-r--r--src/designer/src/lib/shared/shared_settings_p.h142
-rw-r--r--src/designer/src/lib/shared/sheet_delegate.cpp112
-rw-r--r--src/designer/src/lib/shared/sheet_delegate_p.h85
-rw-r--r--src/designer/src/lib/shared/signalslotdialog.cpp526
-rw-r--r--src/designer/src/lib/shared/signalslotdialog.ui129
-rw-r--r--src/designer/src/lib/shared/signalslotdialog_p.h173
-rw-r--r--src/designer/src/lib/shared/spacer_widget.cpp280
-rw-r--r--src/designer/src/lib/shared/spacer_widget_p.h117
-rw-r--r--src/designer/src/lib/shared/stylesheeteditor.cpp409
-rw-r--r--src/designer/src/lib/shared/stylesheeteditor_p.h144
-rw-r--r--src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui67
-rw-r--r--src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui71
-rw-r--r--src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui71
-rw-r--r--src/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui18
-rw-r--r--src/designer/src/lib/shared/templates/forms/Main_Window.ui24
-rw-r--r--src/designer/src/lib/shared/templates/forms/Widget.ui21
-rw-r--r--src/designer/src/lib/shared/textpropertyeditor.cpp430
-rw-r--r--src/designer/src/lib/shared/textpropertyeditor_p.h156
-rw-r--r--src/designer/src/lib/shared/widgetdatabase.cpp865
-rw-r--r--src/designer/src/lib/shared/widgetdatabase_p.h210
-rw-r--r--src/designer/src/lib/shared/widgetfactory.cpp899
-rw-r--r--src/designer/src/lib/shared/widgetfactory_p.h191
-rw-r--r--src/designer/src/lib/shared/zoomwidget.cpp570
-rw-r--r--src/designer/src/lib/shared/zoomwidget_p.h231
-rw-r--r--src/designer/src/plugins/activeqt/activeqt.pro32
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp117
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetextrainfo.h91
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetplugin.cpp146
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetplugin.h77
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp189
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h99
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp186
-rw-r--r--src/designer/src/plugins/activeqt/qaxwidgettaskmenu.h76
-rw-r--r--src/designer/src/plugins/activeqt/qdesigneraxwidget.cpp272
-rw-r--r--src/designer/src/plugins/activeqt/qdesigneraxwidget.h142
-rw-r--r--src/designer/src/plugins/phononwidgets/images/seekslider.pngbin0 -> 444 bytes
-rw-r--r--src/designer/src/plugins/phononwidgets/images/videoplayer.pngbin0 -> 644 bytes
-rw-r--r--src/designer/src/plugins/phononwidgets/images/videowidget.pngbin0 -> 794 bytes
-rw-r--r--src/designer/src/plugins/phononwidgets/images/volumeslider.pngbin0 -> 470 bytes
-rw-r--r--src/designer/src/plugins/phononwidgets/phononcollection.cpp82
-rw-r--r--src/designer/src/plugins/phononwidgets/phononwidgets.pro24
-rw-r--r--src/designer/src/plugins/phononwidgets/phononwidgets.qrc8
-rw-r--r--src/designer/src/plugins/phononwidgets/seeksliderplugin.cpp117
-rw-r--r--src/designer/src/plugins/phononwidgets/seeksliderplugin.h75
-rw-r--r--src/designer/src/plugins/phononwidgets/videoplayerplugin.cpp135
-rw-r--r--src/designer/src/plugins/phononwidgets/videoplayerplugin.h75
-rw-r--r--src/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp154
-rw-r--r--src/designer/src/plugins/phononwidgets/videoplayertaskmenu.h83
-rw-r--r--src/designer/src/plugins/phononwidgets/volumesliderplugin.cpp117
-rw-r--r--src/designer/src/plugins/phononwidgets/volumesliderplugin.h75
-rw-r--r--src/designer/src/plugins/plugins.pri8
-rw-r--r--src/designer/src/plugins/plugins.pro10
-rw-r--r--src/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro13
-rw-r--r--src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp132
-rw-r--r--src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h74
-rw-r--r--src/designer/src/plugins/qwebview/images/qwebview.pngbin0 -> 1473 bytes
-rw-r--r--src/designer/src/plugins/qwebview/qwebview.pro15
-rw-r--r--src/designer/src/plugins/qwebview/qwebview_plugin.cpp137
-rw-r--r--src/designer/src/plugins/qwebview/qwebview_plugin.h74
-rw-r--r--src/designer/src/plugins/qwebview/qwebview_plugin.qrc5
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d.cpp492
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d.h77
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d.pro17
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d_global.h61
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d_plugin.cpp115
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d_plugin.h82
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d_tool.cpp88
-rw-r--r--src/designer/src/plugins/tools/view3d/view3d_tool.h76
-rw-r--r--src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp183
-rw-r--r--src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h95
-rw-r--r--src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp120
-rw-r--r--src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp151
-rw-r--r--src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h93
-rw-r--r--src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp121
-rw-r--r--src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp249
-rw-r--r--src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h96
-rw-r--r--src/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp121
-rw-r--r--src/designer/src/plugins/widgets/q3listview/q3listview_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp130
-rw-r--r--src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h84
-rw-r--r--src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp118
-rw-r--r--src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp196
-rw-r--r--src/designer/src/plugins/widgets/q3table/q3table_extrainfo.h93
-rw-r--r--src/designer/src/plugins/widgets/q3table/q3table_plugin.cpp121
-rw-r--r--src/designer/src/plugins/widgets/q3table/q3table_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp116
-rw-r--r--src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h93
-rw-r--r--src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp122
-rw-r--r--src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp108
-rw-r--r--src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h92
-rw-r--r--src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp128
-rw-r--r--src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp601
-rw-r--r--src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h287
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp115
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h84
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp118
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp217
-rw-r--r--src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h108
-rw-r--r--src/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp235
-rw-r--r--src/designer/src/plugins/widgets/q3wizard/q3wizard_container.h149
-rw-r--r--src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp128
-rw-r--r--src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h76
-rw-r--r--src/designer/src/plugins/widgets/qt3supportwidgets.cpp107
-rw-r--r--src/designer/src/plugins/widgets/widgets.pro82
-rw-r--r--src/designer/src/sharedcomponents.pri30
-rw-r--r--src/designer/src/src.pro12
781 files changed, 134932 insertions, 0 deletions
diff --git a/src/designer/data/generate_header.xsl b/src/designer/data/generate_header.xsl
new file mode 100644
index 000000000..127f00557
--- /dev/null
+++ b/src/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) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/data/generate_impl.xsl b/src/designer/data/generate_impl.xsl
new file mode 100644
index 000000000..a22862e0c
--- /dev/null
+++ b/src/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) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/data/generate_shared.xsl b/src/designer/data/generate_shared.xsl
new file mode 100644
index 000000000..ec95fe2b8
--- /dev/null
+++ b/src/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/src/designer/data/ui3.xsd b/src/designer/data/ui3.xsd
new file mode 100644
index 000000000..06f325ef3
--- /dev/null
+++ b/src/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/src/designer/data/ui4.xsd b/src/designer/data/ui4.xsd
new file mode 100644
index 000000000..53bae62e2
--- /dev/null
+++ b/src/designer/data/ui4.xsd
@@ -0,0 +1,589 @@
+<?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:element name="propertyspecifications" type="PropertySpecifications" 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:attribute name="alignment" type="xs:string" />
+ </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" minOccurs="0" 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="theme" type="xs:string" />
+ <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:complexType name="PropertySpecifications">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="stringpropertyspecification" type="StringPropertySpecification" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="StringPropertySpecification">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="type" type="xs:string" use="required" />
+ <xs:attribute name="notr" type="xs:string"/>
+ </xs:complexType>
+
+</xs:schema>
diff --git a/src/designer/designer.pro b/src/designer/designer.pro
new file mode 100644
index 000000000..721c4fc42
--- /dev/null
+++ b/src/designer/designer.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+CONFIG += qt
+
+SUBDIRS = src
diff --git a/src/designer/src/components/buddyeditor/buddyeditor.cpp b/src/designer/src/components/buddyeditor/buddyeditor.cpp
new file mode 100644
index 000000000..34e1681ef
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <metadatabase_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));
+ // Refuse No-focus unless the widget is promoted.
+ return (ok && q != Qt::NoFocus) || qdesigner_internal::isPromoted(form->core(), w);
+ }
+ }
+ 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 = background()->findChildren<QLabel*>();
+ foreach (QLabel *label, label_list) {
+ const QString buddy_name = buddy(label, m_formWindow->core());
+ if (buddy_name.isEmpty())
+ continue;
+
+ const QList<QWidget *> targets = background()->findChildren<QWidget*>(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 = background->findChildren<QLabel*>();
+ foreach (QLabel *label, label_list) {
+ const QString buddy_name = buddy(label, m_formWindow->core());
+ if (buddy_name.isEmpty())
+ continue;
+ QWidget *target = background->findChild<QWidget*>(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 = widget->findChildren<QWidget*>();
+ 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 = background()->findChildren<QLabel*>();
+ 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 (l->layoutDirection()) {
+ case Qt::LayoutDirectionAuto:
+ 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/src/designer/src/components/buddyeditor/buddyeditor.h b/src/designer/src/components/buddyeditor/buddyeditor.h
new file mode 100644
index 000000000..2cd60071e
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/buddyeditor/buddyeditor.pri b/src/designer/src/components/buddyeditor/buddyeditor.pri
new file mode 100644
index 000000000..c507aa01d
--- /dev/null
+++ b/src/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/src/designer/src/components/buddyeditor/buddyeditor_global.h b/src/designer/src/components/buddyeditor/buddyeditor_global.h
new file mode 100644
index 000000000..00b216b67
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/buddyeditor/buddyeditor_instance.cpp b/src/designer/src/components/buddyeditor/buddyeditor_instance.cpp
new file mode 100644
index 000000000..ef71ec32c
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_instance.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "buddyeditor_plugin.h"
+
+QT_USE_NAMESPACE
+
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(BuddyEditorPlugin)
diff --git a/src/designer/src/components/buddyeditor/buddyeditor_plugin.cpp b/src/designer/src/components/buddyeditor/buddyeditor_plugin.cpp
new file mode 100644
index 000000000..17b93e1b5
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_plugin.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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"));
+ QIcon buddyIcon = QIcon::fromTheme("designer-edit-buddy",
+ QIcon(core->resourceLocation() + QLatin1String("/buddytool.png")));
+ m_action->setIcon(buddyIcon);
+ 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/src/designer/src/components/buddyeditor/buddyeditor_plugin.h b/src/designer/src/components/buddyeditor/buddyeditor_plugin.h
new file mode 100644
index 000000000..7e6e51550
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_plugin.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/buddyeditor/buddyeditor_tool.cpp b/src/designer/src/components/buddyeditor/buddyeditor_tool.cpp
new file mode 100644
index 000000000..3779789fa
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_tool.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/buddyeditor/buddyeditor_tool.h b/src/designer/src/components/buddyeditor/buddyeditor_tool.h
new file mode 100644
index 000000000..dabb4654d
--- /dev/null
+++ b/src/designer/src/components/buddyeditor/buddyeditor_tool.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/component.pri b/src/designer/src/components/component.pri
new file mode 100644
index 000000000..c2fc10d9e
--- /dev/null
+++ b/src/designer/src/components/component.pri
@@ -0,0 +1,2 @@
+
+TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end
diff --git a/src/designer/src/components/components.pro b/src/designer/src/components/components.pro
new file mode 100644
index 000000000..97d79b4bb
--- /dev/null
+++ b/src/designer/src/components/components.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS = lib
diff --git a/src/designer/src/components/formeditor/brushmanagerproxy.cpp b/src/designer/src/components/formeditor/brushmanagerproxy.cpp
new file mode 100644
index 000000000..59803336e
--- /dev/null
+++ b/src/designer/src/components/formeditor/brushmanagerproxy.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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()
+{
+}
+
+void BrushManagerProxy::setBrushManager(QtBrushManager *manager)
+{
+ if (d_ptr->m_Manager == manager)
+ return;
+
+ if (d_ptr->m_Manager) {
+ disconnect(d_ptr->m_Manager, SIGNAL(brushAdded(QString,QBrush)),
+ this, SLOT(brushAdded(QString,QBrush)));
+ disconnect(d_ptr->m_Manager, SIGNAL(brushRemoved(QString)),
+ this, SLOT(brushRemoved(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/src/designer/src/components/formeditor/brushmanagerproxy.h b/src/designer/src/components/formeditor/brushmanagerproxy.h
new file mode 100644
index 000000000..934bd8d46
--- /dev/null
+++ b/src/designer/src/components/formeditor/brushmanagerproxy.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ QScopedPointer<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/src/designer/src/components/formeditor/default_actionprovider.cpp b/src/designer/src/components/formeditor/default_actionprovider.cpp
new file mode 100644
index 000000000..c0a51dede
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_actionprovider.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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, Qt::LayoutDirection 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, Qt::LayoutDirection layoutDirection) const
+{
+ QAction *action = actionAt(pos);
+ if (!action)
+ return QRect();
+ QRect rc = actionGeometry(action);
+ return orientation() == Qt::Horizontal ? horizontalIndicatorRect(rc, layoutDirection) : 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, m_indicator->layoutDirection());
+ 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, Qt::LayoutDirection layoutDirection) const
+{
+ const QRect actionRect = ActionProviderBase::indicatorGeometry(pos, layoutDirection);
+ 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, layoutDirection) : 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/src/designer/src/components/formeditor/default_actionprovider.h b/src/designer/src/components/formeditor/default_actionprovider.h
new file mode 100644
index 000000000..9eba71eef
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_actionprovider.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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, Qt::LayoutDirection layoutDirection) 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, Qt::LayoutDirection layoutDirection) 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/src/designer/src/components/formeditor/default_container.cpp b/src/designer/src/components/formeditor/default_container.cpp
new file mode 100644
index 000000000..e5f2c5b87
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_container.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/default_container.h b/src/designer/src/components/formeditor/default_container.h
new file mode 100644
index 000000000..753f39794
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_container.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/default_layoutdecoration.cpp b/src/designer/src/components/formeditor/default_layoutdecoration.cpp
new file mode 100644
index 000000000..95f190d5d
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_layoutdecoration.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/default_layoutdecoration.h b/src/designer/src/components/formeditor/default_layoutdecoration.h
new file mode 100644
index 000000000..ee876e88e
--- /dev/null
+++ b/src/designer/src/components/formeditor/default_layoutdecoration.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/defaultbrushes.xml b/src/designer/src/components/formeditor/defaultbrushes.xml
new file mode 100644
index 000000000..88035c3a6
--- /dev/null
+++ b/src/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/src/designer/src/components/formeditor/deviceprofiledialog.cpp b/src/designer/src/components/formeditor/deviceprofiledialog.cpp
new file mode 100644
index 000000000..b7030689d
--- /dev/null
+++ b/src/designer/src/components/formeditor/deviceprofiledialog.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/deviceprofiledialog.h b/src/designer/src/components/formeditor/deviceprofiledialog.h
new file mode 100644
index 000000000..e35f30077
--- /dev/null
+++ b/src/designer/src/components/formeditor/deviceprofiledialog.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/components/formeditor/deviceprofiledialog.ui b/src/designer/src/components/formeditor/deviceprofiledialog.ui
new file mode 100644
index 000000000..d7a298c67
--- /dev/null
+++ b/src/designer/src/components/formeditor/deviceprofiledialog.ui
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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" name="SystemSettingsWidget" native="true">
+ <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" name="m_dpiChooser" native="true"/>
+ </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>
+ <tabstops>
+ <tabstop>m_nameLineEdit</tabstop>
+ <tabstop>m_systemFontComboBox</tabstop>
+ <tabstop>m_systemFontSizeCombo</tabstop>
+ <tabstop>m_styleCombo</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/designer/src/components/formeditor/dpi_chooser.cpp b/src/designer/src/components/formeditor/dpi_chooser.cpp
new file mode 100644
index 000000000..6d665dd79
--- /dev/null
+++ b/src/designer/src/components/formeditor/dpi_chooser.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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), QVariant::fromValue(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), QVariant::fromValue(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/src/designer/src/components/formeditor/dpi_chooser.h b/src/designer/src/components/formeditor/dpi_chooser.h
new file mode 100644
index 000000000..10e3c72d8
--- /dev/null
+++ b/src/designer/src/components/formeditor/dpi_chooser.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/components/formeditor/embeddedoptionspage.cpp b/src/designer/src/components/formeditor/embeddedoptionspage.cpp
new file mode 100644
index 000000000..10f4509df
--- /dev/null
+++ b/src/designer/src/components/formeditor/embeddedoptionspage.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/embeddedoptionspage.h b/src/designer/src/components/formeditor/embeddedoptionspage.h
new file mode 100644
index 000000000..7947c3790
--- /dev/null
+++ b/src/designer/src/components/formeditor/embeddedoptionspage.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formeditor.cpp b/src/designer/src/components/formeditor/formeditor.cpp
new file mode 100644
index 000000000..847b99de3
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(QString)),
+ this, SLOT(slotQrcFileChangedExternally(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/src/designer/src/components/formeditor/formeditor.h b/src/designer/src/components/formeditor/formeditor.h
new file mode 100644
index 000000000..88c24b84e
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formeditor.pri b/src/designer/src/components/formeditor/formeditor.pri
new file mode 100644
index 000000000..b1a93188a
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor.pri
@@ -0,0 +1,77 @@
+
+QT += xml
+
+INCLUDEPATH += $$PWD
+
+FORMS += $$PWD/deviceprofiledialog.ui \
+ $$PWD/formwindowsettings.ui \
+ $$PWD/templateoptionspage.ui
+
+HEADERS += $$PWD/qdesigner_resource.h \
+ $$PWD/qdesignerundostack.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/qdesignerundostack.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/src/designer/src/components/formeditor/formeditor.qrc b/src/designer/src/components/formeditor/formeditor.qrc
new file mode 100644
index 000000000..e42cc66ec
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor.qrc
@@ -0,0 +1,175 @@
+<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/cleartext.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/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/simplifyrichtext.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>
+ <file>images/mac/simplifyrichtext.png</file>
+ </qresource>
+ <qresource prefix="/trolltech/brushes">
+ <file>defaultbrushes.xml</file>
+ </qresource>
+</RCC>
diff --git a/src/designer/src/components/formeditor/formeditor_global.h b/src/designer/src/components/formeditor/formeditor_global.h
new file mode 100644
index 000000000..f5df69114
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formeditor_optionspage.cpp b/src/designer/src/components/formeditor/formeditor_optionspage.cpp
new file mode 100644
index 000000000..e50072aac
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor_optionspage.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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();
+
+ for (IntList::const_iterator it = zoomValues.constBegin(); it != cend; ++it) {
+ //: Zoom percentage
+ 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/src/designer/src/components/formeditor/formeditor_optionspage.h b/src/designer/src/components/formeditor/formeditor_optionspage.h
new file mode 100644
index 000000000..d7d169be2
--- /dev/null
+++ b/src/designer/src/components/formeditor/formeditor_optionspage.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formwindow.cpp b/src/designer/src/components/formeditor/formwindow.cpp
new file mode 100644
index 000000000..3fb18aa31
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow.cpp
@@ -0,0 +1,2981 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = start->findChildren<QWidget*>();
+ foreach (QWidget *widget, widgets) {
+ if (!qobject_cast<WidgetHandle*>(widget)) {
+ widget->setCursor(c);
+ }
+ }
+#endif
+}
+
+void FormWindow::init()
+{
+ if (FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager())) {
+ manager->undoGroup()->addStack(m_undoStack.qundoStack());
+ }
+
+ 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_undoStack, SIGNAL(changed()), this, SIGNAL(changed()));
+ connect(&m_undoStack, SIGNAL(changed()), 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("windowOpacity")), 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 = w->findChildren<QWidget*>();
+ 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 = main->findChildren<QWidget*>();
+ if (!widgetChildren.empty())
+ insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames);
+
+ const QList<QLayout *> layoutChildren = main->findChildren<QLayout*>();
+ if (!layoutChildren.empty())
+ insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames);
+
+ const QList<QAction *> actionChildren = main->findChildren<QAction*>();
+ if (!actionChildren.empty())
+ insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames);
+
+ const QList<QButtonGroup *> buttonGroupChildren = main->findChildren<QButtonGroup*>();
+ 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_undoStack.push(cmd);
+ }
+
+ m_undoStack.push(geom_cmd);
+
+ InsertWidgetCommand *cmd = new InsertWidgetCommand(this);
+ cmd->init(w, already_in_form);
+ m_undoStack.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;
+ SetPropertyCommand *cmd = new SetPropertyCommand(this);
+ cmd->init(widget, QLatin1String("geometry"), r);
+ cmd->setText(tr("Resize"));
+ m_undoStack.push(cmd);
+}
+
+void FormWindow::raiseChildSelections(QWidget *w)
+{
+ const QWidgetList l = w->findChildren<QWidget*>();
+ 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 = mainContainer()->findChildren<QWidget*>();
+ 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);
+}
+
+// ArrowKeyOperation: Stores a keyboard move or resize (Shift pressed)
+// operation.
+struct ArrowKeyOperation {
+ ArrowKeyOperation() : resize(false), distance(0), arrowKey(Qt::Key_Left) {}
+
+ QRect apply(const QRect &in) const;
+
+ bool resize; // Resize: Shift-Key->drag bottom/right corner, else just move
+ int distance;
+ int arrowKey;
+};
+
+} // namespace
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(qdesigner_internal::ArrowKeyOperation)
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QRect ArrowKeyOperation::apply(const QRect &rect) const
+{
+ QRect r = rect;
+ if (resize) {
+ if (arrowKey == Qt::Key_Left || arrowKey == Qt::Key_Right)
+ r.setWidth(r.width() + distance);
+ else
+ r.setHeight(r.height() + distance);
+ } else {
+ if (arrowKey == Qt::Key_Left || arrowKey == Qt::Key_Right)
+ r.moveLeft(r.x() + distance);
+ else
+ r.moveTop(r.y() + distance);
+ }
+ return r;
+}
+
+QDebug operator<<(QDebug in, const ArrowKeyOperation &op)
+{
+ in.nospace() << "Resize=" << op.resize << " dist=" << op.distance << " Key=" << op.arrowKey << ' ';
+ return in;
+}
+
+// ArrowKeyPropertyHelper: Applies a struct ArrowKeyOperation
+// (stored as new value) to a list of widgets using to calculate the
+// changed geometry of the widget in setValue(). Thus, the 'newValue'
+// of the property command is the relative move distance, which is the same
+// for all widgets (although resulting in different geometries for the widgets).
+// The command merging can then work as it would when applying the same text
+// to all QLabels.
+
+class ArrowKeyPropertyHelper : public PropertyHelper {
+public:
+ ArrowKeyPropertyHelper(QObject* o, SpecialProperty sp,
+ QDesignerPropertySheetExtension *s, int i) :
+ PropertyHelper(o, sp, s, i) {}
+
+ virtual Value setValue(QDesignerFormWindowInterface *fw, const QVariant &value, bool changed, unsigned subPropertyMask);
+};
+
+PropertyHelper::Value ArrowKeyPropertyHelper::setValue(QDesignerFormWindowInterface *fw, const QVariant &value, bool changed, unsigned subPropertyMask)
+{
+ // Apply operation to obtain the new geometry value.
+ QWidget *w = qobject_cast<QWidget*>(object());
+ const ArrowKeyOperation operation = qvariant_cast<ArrowKeyOperation>(value);
+ const QRect newGeom = operation.apply(w->geometry());
+ return PropertyHelper::setValue(fw, QVariant(newGeom), changed, subPropertyMask);
+}
+
+// ArrowKeyPropertyCommand: Helper factory overwritten to create
+// ArrowKeyPropertyHelper and a merge operation that merges values of
+// the same direction.
+class ArrowKeyPropertyCommand: public SetPropertyCommand {
+public:
+ explicit ArrowKeyPropertyCommand(QDesignerFormWindowInterface *fw,
+ QUndoCommand *p = 0);
+
+ void init(QWidgetList &l, const ArrowKeyOperation &op);
+
+protected:
+ virtual PropertyHelper *createPropertyHelper(QObject *o, SpecialProperty sp,
+ QDesignerPropertySheetExtension *s, int i) const
+ { return new ArrowKeyPropertyHelper(o, sp, s, i); }
+ virtual QVariant mergeValue(const QVariant &newValue);
+};
+
+ArrowKeyPropertyCommand::ArrowKeyPropertyCommand(QDesignerFormWindowInterface *fw,
+ QUndoCommand *p) :
+ SetPropertyCommand(fw, p)
+{
+ static const int mid = qRegisterMetaType<qdesigner_internal::ArrowKeyOperation>();
+ Q_UNUSED(mid)
+}
+
+void ArrowKeyPropertyCommand::init(QWidgetList &l, const ArrowKeyOperation &op)
+{
+ QObjectList ol;
+ foreach(QWidget *w, l)
+ ol.push_back(w);
+ SetPropertyCommand::init(ol, QLatin1String("geometry"), QVariant::fromValue(op));
+
+ setText(op.resize ? FormWindow::tr("Key Resize") : FormWindow::tr("Key Move"));
+}
+
+QVariant ArrowKeyPropertyCommand::mergeValue(const QVariant &newMergeValue)
+{
+ // Merge move operations of the same arrow key
+ if (!newMergeValue.canConvert<ArrowKeyOperation>())
+ return QVariant();
+ ArrowKeyOperation mergedOperation = qvariant_cast<ArrowKeyOperation>(newValue());
+ const ArrowKeyOperation newMergeOperation = qvariant_cast<ArrowKeyOperation>(newMergeValue);
+ if (mergedOperation.resize != newMergeOperation.resize || mergedOperation.arrowKey != newMergeOperation.arrowKey)
+ return QVariant();
+ mergedOperation.distance += newMergeOperation.distance;
+ return QVariant::fromValue(mergedOperation);
+}
+
+void FormWindow::handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers)
+{
+ 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);
+
+ ArrowKeyOperation operation;
+ operation.resize = modifiers & Qt::ShiftModifier;
+ operation.distance = newValue - oldValue;
+ operation.arrowKey = key;
+
+ ArrowKeyPropertyCommand *cmd = new ArrowKeyPropertyCommand(this);
+ cmd->init(selection, operation);
+ m_undoStack.push(cmd);
+}
+
+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
+{
+ if (m_core->widgetDataBase()->isContainer(outerContainer))
+ if (const QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer)) {
+ const int currentIndex = container->currentIndex();
+ return currentIndex >= 0 ?
+ container->widget(currentIndex) :
+ static_cast<QWidget *>(0);
+ }
+ 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. No empty page-based containers.
+ containerOfW = innerContainer(containerOfW);
+ if (!containerOfW)
+ break;
+ 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 (!w)
+ return 0;
+ 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_undoStack.push(cmd);
+ selectWidget(w);
+ }
+ }
+
+ if (actionCount)
+ foreach (QAction *a, clipboard.m_actions) {
+ ensureUniqueObjectName(a);
+ AddActionCommand *cmd = new AddActionCommand(this);
+ cmd->init(a);
+ m_undoStack.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)
+{
+ m_undoStack.beginMacro(description);
+}
+
+void FormWindow::endCommand()
+{
+ m_undoStack.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_undoStack.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_undoStack.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)) {
+ const int index = container->currentIndex();
+ if (index < 0)
+ return false;
+ widget = container->widget(index);
+ }
+
+ 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(QVariant::fromValue(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);
+ }
+
+ if (manager->actionLower()->isEnabled()) {
+ popup->addAction(manager->actionLower());
+ popup->addAction(manager->actionRaise());
+ popup->addSeparator();
+ }
+ 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());
+ if (!isFormWindow) {
+ layoutMenu->addAction(manager->actionSplitHorizontal());
+ layoutMenu->addAction(manager->actionSplitVertical());
+ }
+ layoutMenu->addAction(manager->actionGridLayout());
+ layoutMenu->addAction(manager->actionFormLayout());
+ 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_undoStack.isDirty();
+}
+
+void FormWindow::setDirty(bool dirty)
+{
+ m_undoStack.setDirty(dirty);
+}
+
+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;
+ v.setValue(e);
+ SetPropertyCommand *cmd = new SetPropertyCommand(this);
+ cmd->init(widget, dockWidgetAreaName, v);
+ m_undoStack.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();
+}
+
+QUndoStack *FormWindow::commandHistory() const
+{
+ return const_cast<QDesignerUndoStack &>(m_undoStack).qundoStack();
+}
+
+} // namespace
+
+QT_END_NAMESPACE
+
diff --git a/src/designer/src/components/formeditor/formwindow.h b/src/designer/src/components/formeditor/formwindow.h
new file mode 100644
index 000000000..ff862d863
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow.h
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOW_H
+#define FORMWINDOW_H
+
+#include "formeditor_global.h"
+#include "qdesignerundostack.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 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);
+
+ virtual QUndoStack *commandHistory() const;
+ 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 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;
+ 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);
+
+ 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;
+
+ QDesignerUndoStack m_undoStack;
+
+ 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;
+
+ 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;
+
+ QPoint m_contextMenuPosition;
+
+private:
+ friend class WidgetEditorTool;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOW_H
diff --git a/src/designer/src/components/formeditor/formwindow_dnditem.cpp b/src/designer/src/components/formeditor/formwindow_dnditem.cpp
new file mode 100644
index 000000000..5b8f86b0f
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow_dnditem.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/formwindow_dnditem.h b/src/designer/src/components/formeditor/formwindow_dnditem.h
new file mode 100644
index 000000000..4911c16b5
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow_dnditem.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formwindow_widgetstack.cpp b/src/designer/src/components/formeditor/formwindow_widgetstack.cpp
new file mode 100644
index 000000000..ac20e8ac1
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow_widgetstack.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 QStackedLayout),
+ m_layout(new QStackedLayout)
+{
+ m_layout->setMargin(0);
+ m_layout->setSpacing(0);
+ m_layout->setStackingMode(QStackedLayout::StackAll);
+
+ // We choose a QStackedLayout as immediate layout for
+ // the form windows as it ignores the sizePolicy of
+ // its child (for example, Fixed would cause undesired side effects).
+ m_formContainerLayout->setMargin(0);
+ m_formContainer->setObjectName(QLatin1String("formContainer"));
+ m_formContainer->setLayout(m_formContainerLayout);
+ m_formContainerLayout->setStackingMode(QStackedLayout::StackAll);
+ // 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/src/designer/src/components/formeditor/formwindow_widgetstack.h b/src/designer/src/components/formeditor/formwindow_widgetstack.h
new file mode 100644
index 000000000..56f9743bb
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindow_widgetstack.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOW_WIDGETSTACK_H
+#define FORMWINDOW_WIDGETSTACK_H
+
+#include "formeditor_global.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowToolInterface;
+
+class QStackedLayout;
+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;
+ QStackedLayout *m_formContainerLayout;
+ QStackedLayout *m_layout;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOW_WIDGETSTACK_H
diff --git a/src/designer/src/components/formeditor/formwindowcursor.cpp b/src/designer/src/components/formeditor/formwindowcursor.cpp
new file mode 100644
index 000000000..51d563001
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowcursor.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/formwindowcursor.h b/src/designer/src/components/formeditor/formwindowcursor.h
new file mode 100644
index 000000000..797aab446
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowcursor.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formwindowmanager.cpp b/src/designer/src/components/formeditor/formwindowmanager.cpp
new file mode 100644
index 000000000..1d662b27c
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowmanager.cpp
@@ -0,0 +1,1036 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// 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::WinIdChange:
+ case QEvent::DynamicPropertyChange:
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ case QEvent::HoverMove:
+ case QEvent::AcceptDropsChange:
+ 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()));
+
+ QIcon formIcon = QIcon::fromTheme("designer-form-layout", createIconSet(QLatin1String("editform.png")));
+ QAction *actionFormLayout = new QAction(formIcon, 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(QIcon::fromTheme("edit-undo", createIconSet(QLatin1String("undo.png"))));
+ m_actionRedo = m_undoGroup->createRedoAction(this);
+ m_actionRedo->setEnabled(false);
+ m_actionRedo->setIcon(QIcon::fromTheme("edit-redo", 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);
+
+#ifdef Q_WS_X11
+ m_actionCopy->setIcon(QIcon::fromTheme("edit-copy", m_actionCopy->icon()));
+ m_actionCut->setIcon(QIcon::fromTheme("edit-cut", m_actionCut->icon()));
+ m_actionPaste->setIcon(QIcon::fromTheme("edit-paste", m_actionPaste->icon()));
+ m_actionDelete->setIcon(QIcon::fromTheme("edit-delete", m_actionDelete->icon()));
+
+ // These do not currently exist, but will allow theme authors to fill in the gaps
+ m_actionBreakLayout->setIcon(QIcon::fromTheme("designer-break-layout", m_actionBreakLayout->icon()));
+ m_actionGridLayout->setIcon(QIcon::fromTheme("designer-grid-layout", m_actionGridLayout->icon()));
+ m_actionHorizontalLayout->setIcon(QIcon::fromTheme("designer-horizontal-layout", m_actionHorizontalLayout->icon()));
+ m_actionVerticalLayout->setIcon(QIcon::fromTheme("designer-vertical-layout", m_actionVerticalLayout->icon()));
+ m_actionSplitHorizontal->setIcon(QIcon::fromTheme("designer-split-horizontal", m_actionSplitHorizontal->icon()));
+ m_actionSplitVertical->setIcon(QIcon::fromTheme("designer-split-vertical", m_actionSplitVertical->icon()));
+ m_actionAdjustSize->setIcon(QIcon::fromTheme("designer-adjust-size", m_actionAdjustSize->icon()));
+#endif
+}
+
+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/src/designer/src/components/formeditor/formwindowmanager.h b/src/designer/src/components/formeditor/formwindowmanager.h
new file mode 100644
index 000000000..dfd421522
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowmanager.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formwindowsettings.cpp b/src/designer/src/components/formeditor/formwindowsettings.cpp
new file mode 100644
index 000000000..04d5f8ca5
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowsettings.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/formwindowsettings.h b/src/designer/src/components/formeditor/formwindowsettings.h
new file mode 100644
index 000000000..f5c6f53e3
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowsettings.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/formwindowsettings.ui b/src/designer/src/components/formeditor/formwindowsettings.ui
new file mode 100644
index 000000000..1a607b263
--- /dev/null
+++ b/src/designer/src/components/formeditor/formwindowsettings.ui
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/formeditor/iconcache.cpp b/src/designer/src/components/formeditor/iconcache.cpp
new file mode 100644
index 000000000..3fceeeade
--- /dev/null
+++ b/src/designer/src/components/formeditor/iconcache.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/iconcache.h b/src/designer/src/components/formeditor/iconcache.h
new file mode 100644
index 000000000..5d9cc6580
--- /dev/null
+++ b/src/designer/src/components/formeditor/iconcache.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/images/cleartext.png b/src/designer/src/components/formeditor/images/cleartext.png
new file mode 100644
index 000000000..74133baff
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cleartext.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/color.png b/src/designer/src/components/formeditor/images/color.png
new file mode 100644
index 000000000..54b7ebcde
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/color.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/configure.png b/src/designer/src/components/formeditor/images/configure.png
new file mode 100644
index 000000000..d9f2fd8c0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/configure.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/arrow.png b/src/designer/src/components/formeditor/images/cursors/arrow.png
new file mode 100644
index 000000000..a69ef4eb6
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/arrow.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/busy.png b/src/designer/src/components/formeditor/images/cursors/busy.png
new file mode 100644
index 000000000..53717e499
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/busy.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/closedhand.png b/src/designer/src/components/formeditor/images/cursors/closedhand.png
new file mode 100644
index 000000000..b78dd1dac
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/closedhand.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/cross.png b/src/designer/src/components/formeditor/images/cursors/cross.png
new file mode 100644
index 000000000..fe38e7448
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/cross.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/hand.png b/src/designer/src/components/formeditor/images/cursors/hand.png
new file mode 100644
index 000000000..d2004aefa
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/hand.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/hsplit.png b/src/designer/src/components/formeditor/images/cursors/hsplit.png
new file mode 100644
index 000000000..a5667e3ff
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/hsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/ibeam.png b/src/designer/src/components/formeditor/images/cursors/ibeam.png
new file mode 100644
index 000000000..097fc5fa7
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/ibeam.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/no.png b/src/designer/src/components/formeditor/images/cursors/no.png
new file mode 100644
index 000000000..2b08c4e2a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/no.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/openhand.png b/src/designer/src/components/formeditor/images/cursors/openhand.png
new file mode 100644
index 000000000..9181c859e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/openhand.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/sizeall.png b/src/designer/src/components/formeditor/images/cursors/sizeall.png
new file mode 100644
index 000000000..69f13eb34
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/sizeall.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/sizeb.png b/src/designer/src/components/formeditor/images/cursors/sizeb.png
new file mode 100644
index 000000000..3b127a05d
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/sizeb.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/sizef.png b/src/designer/src/components/formeditor/images/cursors/sizef.png
new file mode 100644
index 000000000..f37d7b91e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/sizef.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/sizeh.png b/src/designer/src/components/formeditor/images/cursors/sizeh.png
new file mode 100644
index 000000000..a9f40cbc3
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/sizeh.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/sizev.png b/src/designer/src/components/formeditor/images/cursors/sizev.png
new file mode 100644
index 000000000..1edbab27a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/sizev.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/uparrow.png b/src/designer/src/components/formeditor/images/cursors/uparrow.png
new file mode 100644
index 000000000..d3e70ef4c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/uparrow.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/vsplit.png b/src/designer/src/components/formeditor/images/cursors/vsplit.png
new file mode 100644
index 000000000..1beda2570
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/vsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/wait.png b/src/designer/src/components/formeditor/images/cursors/wait.png
new file mode 100644
index 000000000..69056c479
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/wait.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/cursors/whatsthis.png b/src/designer/src/components/formeditor/images/cursors/whatsthis.png
new file mode 100644
index 000000000..b47601c37
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/cursors/whatsthis.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/downplus.png b/src/designer/src/components/formeditor/images/downplus.png
new file mode 100644
index 000000000..1e384a72d
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/downplus.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/dropdownbutton.png b/src/designer/src/components/formeditor/images/dropdownbutton.png
new file mode 100644
index 000000000..5dd964946
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/dropdownbutton.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/edit.png b/src/designer/src/components/formeditor/images/edit.png
new file mode 100644
index 000000000..a5e49adf9
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/edit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/editdelete-16.png b/src/designer/src/components/formeditor/images/editdelete-16.png
new file mode 100644
index 000000000..ef5c799c1
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/editdelete-16.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/emptyicon.png b/src/designer/src/components/formeditor/images/emptyicon.png
new file mode 100644
index 000000000..897220e21
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/emptyicon.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/filenew-16.png b/src/designer/src/components/formeditor/images/filenew-16.png
new file mode 100644
index 000000000..eefb3c520
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/filenew-16.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/fileopen-16.png b/src/designer/src/components/formeditor/images/fileopen-16.png
new file mode 100644
index 000000000..d832c621c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/fileopen-16.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/leveldown.png b/src/designer/src/components/formeditor/images/leveldown.png
new file mode 100644
index 000000000..742b7fb84
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/leveldown.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/levelup.png b/src/designer/src/components/formeditor/images/levelup.png
new file mode 100644
index 000000000..48b3e8922
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/levelup.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/adjustsize.png b/src/designer/src/components/formeditor/images/mac/adjustsize.png
new file mode 100644
index 000000000..c4d884c8b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/adjustsize.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/back.png b/src/designer/src/components/formeditor/images/mac/back.png
new file mode 100644
index 000000000..e58177f43
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/back.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/buddytool.png b/src/designer/src/components/formeditor/images/mac/buddytool.png
new file mode 100644
index 000000000..2a4287089
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/buddytool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/down.png b/src/designer/src/components/formeditor/images/mac/down.png
new file mode 100644
index 000000000..29d1d4439
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/down.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editbreaklayout.png b/src/designer/src/components/formeditor/images/mac/editbreaklayout.png
new file mode 100644
index 000000000..dc005590b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editbreaklayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editcopy.png b/src/designer/src/components/formeditor/images/mac/editcopy.png
new file mode 100644
index 000000000..f55136446
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editcopy.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editcut.png b/src/designer/src/components/formeditor/images/mac/editcut.png
new file mode 100644
index 000000000..a784fd570
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editcut.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editdelete.png b/src/designer/src/components/formeditor/images/mac/editdelete.png
new file mode 100644
index 000000000..201b31cdb
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editdelete.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editform.png b/src/designer/src/components/formeditor/images/mac/editform.png
new file mode 100644
index 000000000..4fc2e40dc
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editform.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editgrid.png b/src/designer/src/components/formeditor/images/mac/editgrid.png
new file mode 100644
index 000000000..bba4a695b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editgrid.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/edithlayout.png b/src/designer/src/components/formeditor/images/mac/edithlayout.png
new file mode 100644
index 000000000..ec880bb5c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/edithlayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/edithlayoutsplit.png b/src/designer/src/components/formeditor/images/mac/edithlayoutsplit.png
new file mode 100644
index 000000000..227d0115f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/edithlayoutsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editlower.png b/src/designer/src/components/formeditor/images/mac/editlower.png
new file mode 100644
index 000000000..347806fc0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editlower.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editpaste.png b/src/designer/src/components/formeditor/images/mac/editpaste.png
new file mode 100644
index 000000000..64c0b2d6a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editpaste.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editraise.png b/src/designer/src/components/formeditor/images/mac/editraise.png
new file mode 100644
index 000000000..09cbbd7d5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editraise.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editvlayout.png b/src/designer/src/components/formeditor/images/mac/editvlayout.png
new file mode 100644
index 000000000..63b26cdb2
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editvlayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/editvlayoutsplit.png b/src/designer/src/components/formeditor/images/mac/editvlayoutsplit.png
new file mode 100644
index 000000000..5a02c944e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/editvlayoutsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/filenew.png b/src/designer/src/components/formeditor/images/mac/filenew.png
new file mode 100644
index 000000000..9dcba4284
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/filenew.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/fileopen.png b/src/designer/src/components/formeditor/images/mac/fileopen.png
new file mode 100644
index 000000000..c12bcd507
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/fileopen.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/filesave.png b/src/designer/src/components/formeditor/images/mac/filesave.png
new file mode 100644
index 000000000..b41ecf531
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/filesave.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/forward.png b/src/designer/src/components/formeditor/images/mac/forward.png
new file mode 100644
index 000000000..34b91f09f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/forward.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/insertimage.png b/src/designer/src/components/formeditor/images/mac/insertimage.png
new file mode 100644
index 000000000..b8673e13b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/insertimage.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/minus.png b/src/designer/src/components/formeditor/images/mac/minus.png
new file mode 100644
index 000000000..8d2eaed52
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/minus.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/plus.png b/src/designer/src/components/formeditor/images/mac/plus.png
new file mode 100644
index 000000000..1ee45423e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/plus.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/redo.png b/src/designer/src/components/formeditor/images/mac/redo.png
new file mode 100644
index 000000000..8875bf246
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/redo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/resetproperty.png b/src/designer/src/components/formeditor/images/mac/resetproperty.png
new file mode 100644
index 000000000..9048252ec
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/resetproperty.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/resourceeditortool.png b/src/designer/src/components/formeditor/images/mac/resourceeditortool.png
new file mode 100644
index 000000000..7ef511c2b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/resourceeditortool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/signalslottool.png b/src/designer/src/components/formeditor/images/mac/signalslottool.png
new file mode 100644
index 000000000..71c9b07a8
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/signalslottool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png b/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png
new file mode 100644
index 000000000..a48e974bf
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/simplifyrichtext.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/tabordertool.png b/src/designer/src/components/formeditor/images/mac/tabordertool.png
new file mode 100644
index 000000000..f54faf9ab
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/tabordertool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textanchor.png b/src/designer/src/components/formeditor/images/mac/textanchor.png
new file mode 100644
index 000000000..baa9dda52
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textanchor.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textbold.png b/src/designer/src/components/formeditor/images/mac/textbold.png
new file mode 100644
index 000000000..38400bd1f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textbold.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textcenter.png b/src/designer/src/components/formeditor/images/mac/textcenter.png
new file mode 100644
index 000000000..2ef5b2ee6
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textcenter.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textitalic.png b/src/designer/src/components/formeditor/images/mac/textitalic.png
new file mode 100644
index 000000000..0170ee26a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textitalic.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textjustify.png b/src/designer/src/components/formeditor/images/mac/textjustify.png
new file mode 100644
index 000000000..39cd6c1a9
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textjustify.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textleft.png b/src/designer/src/components/formeditor/images/mac/textleft.png
new file mode 100644
index 000000000..83a66d553
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textleft.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textright.png b/src/designer/src/components/formeditor/images/mac/textright.png
new file mode 100644
index 000000000..e7c04645c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textright.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textsubscript.png b/src/designer/src/components/formeditor/images/mac/textsubscript.png
new file mode 100644
index 000000000..ff431f396
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textsubscript.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textsuperscript.png b/src/designer/src/components/formeditor/images/mac/textsuperscript.png
new file mode 100644
index 000000000..cb67a33d0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textsuperscript.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/textunder.png b/src/designer/src/components/formeditor/images/mac/textunder.png
new file mode 100644
index 000000000..968bac5e9
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/textunder.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/undo.png b/src/designer/src/components/formeditor/images/mac/undo.png
new file mode 100644
index 000000000..a3bd5e0bf
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/undo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/up.png b/src/designer/src/components/formeditor/images/mac/up.png
new file mode 100644
index 000000000..e43731221
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/up.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/mac/widgettool.png b/src/designer/src/components/formeditor/images/mac/widgettool.png
new file mode 100644
index 000000000..e1aa353db
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/mac/widgettool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/minus-16.png b/src/designer/src/components/formeditor/images/minus-16.png
new file mode 100644
index 000000000..745b44572
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/minus-16.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/plus-16.png b/src/designer/src/components/formeditor/images/plus-16.png
new file mode 100644
index 000000000..ef43788e6
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/plus-16.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/prefix-add.png b/src/designer/src/components/formeditor/images/prefix-add.png
new file mode 100644
index 000000000..cfbb053f4
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/prefix-add.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/qt3logo.png b/src/designer/src/components/formeditor/images/qt3logo.png
new file mode 100644
index 000000000..720285001
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/qt3logo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/qtlogo.png b/src/designer/src/components/formeditor/images/qtlogo.png
new file mode 100644
index 000000000..038fa2cc3
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/qtlogo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/reload.png b/src/designer/src/components/formeditor/images/reload.png
new file mode 100644
index 000000000..18c752e14
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/reload.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/resetproperty.png b/src/designer/src/components/formeditor/images/resetproperty.png
new file mode 100644
index 000000000..9048252ec
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/resetproperty.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/sort.png b/src/designer/src/components/formeditor/images/sort.png
new file mode 100644
index 000000000..883bfa9de
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/sort.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/submenu.png b/src/designer/src/components/formeditor/images/submenu.png
new file mode 100644
index 000000000..3deb28e3a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/submenu.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/calendarwidget.png b/src/designer/src/components/formeditor/images/widgets/calendarwidget.png
new file mode 100644
index 000000000..26737b883
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/calendarwidget.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/checkbox.png b/src/designer/src/components/formeditor/images/widgets/checkbox.png
new file mode 100644
index 000000000..ab6f53e02
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/checkbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/columnview.png b/src/designer/src/components/formeditor/images/widgets/columnview.png
new file mode 100644
index 000000000..4132ee6b1
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/columnview.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/combobox.png b/src/designer/src/components/formeditor/images/widgets/combobox.png
new file mode 100644
index 000000000..bf3ed79f7
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/combobox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/commandlinkbutton.png b/src/designer/src/components/formeditor/images/widgets/commandlinkbutton.png
new file mode 100644
index 000000000..6bbd84a97
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/commandlinkbutton.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/dateedit.png b/src/designer/src/components/formeditor/images/widgets/dateedit.png
new file mode 100644
index 000000000..6827fa742
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/dateedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/datetimeedit.png b/src/designer/src/components/formeditor/images/widgets/datetimeedit.png
new file mode 100644
index 000000000..7d8e6fe6d
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/datetimeedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/dial.png b/src/designer/src/components/formeditor/images/widgets/dial.png
new file mode 100644
index 000000000..050d1dbd0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/dial.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png b/src/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png
new file mode 100644
index 000000000..b1f89fbb3
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/dockwidget.png b/src/designer/src/components/formeditor/images/widgets/dockwidget.png
new file mode 100644
index 000000000..9eee04f70
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/dockwidget.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/doublespinbox.png b/src/designer/src/components/formeditor/images/widgets/doublespinbox.png
new file mode 100644
index 000000000..5686ac89b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/doublespinbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/fontcombobox.png b/src/designer/src/components/formeditor/images/widgets/fontcombobox.png
new file mode 100644
index 000000000..6848f15c2
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/fontcombobox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/frame.png b/src/designer/src/components/formeditor/images/widgets/frame.png
new file mode 100644
index 000000000..68f5da0a3
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/frame.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/graphicsview.png b/src/designer/src/components/formeditor/images/widgets/graphicsview.png
new file mode 100644
index 000000000..93fe7603a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/graphicsview.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/groupbox.png b/src/designer/src/components/formeditor/images/widgets/groupbox.png
new file mode 100644
index 000000000..4025b4dc5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/groupbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png b/src/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png
new file mode 100644
index 000000000..62fd1ad56
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/hscrollbar.png b/src/designer/src/components/formeditor/images/widgets/hscrollbar.png
new file mode 100644
index 000000000..466c58de5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/hscrollbar.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/hslider.png b/src/designer/src/components/formeditor/images/widgets/hslider.png
new file mode 100644
index 000000000..525bd1cab
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/hslider.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/hsplit.png b/src/designer/src/components/formeditor/images/widgets/hsplit.png
new file mode 100644
index 000000000..1ea8f2ac0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/hsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/label.png b/src/designer/src/components/formeditor/images/widgets/label.png
new file mode 100644
index 000000000..5d7d7b4cc
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/label.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/lcdnumber.png b/src/designer/src/components/formeditor/images/widgets/lcdnumber.png
new file mode 100644
index 000000000..c3cac1826
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/lcdnumber.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/line.png b/src/designer/src/components/formeditor/images/widgets/line.png
new file mode 100644
index 000000000..5c64dfb59
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/line.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/lineedit.png b/src/designer/src/components/formeditor/images/widgets/lineedit.png
new file mode 100644
index 000000000..75fc890f4
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/lineedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/listbox.png b/src/designer/src/components/formeditor/images/widgets/listbox.png
new file mode 100644
index 000000000..367e67ff5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/listbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/listview.png b/src/designer/src/components/formeditor/images/widgets/listview.png
new file mode 100644
index 000000000..d1308d575
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/listview.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/mdiarea.png b/src/designer/src/components/formeditor/images/widgets/mdiarea.png
new file mode 100644
index 000000000..7783dd527
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/mdiarea.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/plaintextedit.png b/src/designer/src/components/formeditor/images/widgets/plaintextedit.png
new file mode 100644
index 000000000..077bf16cb
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/plaintextedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/progress.png b/src/designer/src/components/formeditor/images/widgets/progress.png
new file mode 100644
index 000000000..44ae094e7
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/progress.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/pushbutton.png b/src/designer/src/components/formeditor/images/widgets/pushbutton.png
new file mode 100644
index 000000000..61f779ce2
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/pushbutton.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/radiobutton.png b/src/designer/src/components/formeditor/images/widgets/radiobutton.png
new file mode 100644
index 000000000..10c1d8c3e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/radiobutton.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/scrollarea.png b/src/designer/src/components/formeditor/images/widgets/scrollarea.png
new file mode 100644
index 000000000..651ea24c0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/scrollarea.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/spacer.png b/src/designer/src/components/formeditor/images/widgets/spacer.png
new file mode 100644
index 000000000..8a0931bf8
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/spacer.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/spinbox.png b/src/designer/src/components/formeditor/images/widgets/spinbox.png
new file mode 100644
index 000000000..cdd9fe141
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/spinbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/tabbar.png b/src/designer/src/components/formeditor/images/widgets/tabbar.png
new file mode 100644
index 000000000..d5d37836b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/tabbar.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/table.png b/src/designer/src/components/formeditor/images/widgets/table.png
new file mode 100644
index 000000000..4bbd9c2d0
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/table.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/tabwidget.png b/src/designer/src/components/formeditor/images/widgets/tabwidget.png
new file mode 100644
index 000000000..1254bb63a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/tabwidget.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/textedit.png b/src/designer/src/components/formeditor/images/widgets/textedit.png
new file mode 100644
index 000000000..32e897d97
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/textedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/timeedit.png b/src/designer/src/components/formeditor/images/widgets/timeedit.png
new file mode 100644
index 000000000..c66d91b2f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/timeedit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/toolbox.png b/src/designer/src/components/formeditor/images/widgets/toolbox.png
new file mode 100644
index 000000000..2ab71dc74
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/toolbox.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/toolbutton.png b/src/designer/src/components/formeditor/images/widgets/toolbutton.png
new file mode 100644
index 000000000..0bff069a5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/toolbutton.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/vline.png b/src/designer/src/components/formeditor/images/widgets/vline.png
new file mode 100644
index 000000000..35a7300a5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/vline.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/vscrollbar.png b/src/designer/src/components/formeditor/images/widgets/vscrollbar.png
new file mode 100644
index 000000000..28b7c40c6
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/vscrollbar.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/vslider.png b/src/designer/src/components/formeditor/images/widgets/vslider.png
new file mode 100644
index 000000000..59f06bae4
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/vslider.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/vspacer.png b/src/designer/src/components/formeditor/images/widgets/vspacer.png
new file mode 100644
index 000000000..ce5e8bd7d
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/vspacer.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/widget.png b/src/designer/src/components/formeditor/images/widgets/widget.png
new file mode 100644
index 000000000..1cf960e61
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/widget.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/widgetstack.png b/src/designer/src/components/formeditor/images/widgets/widgetstack.png
new file mode 100644
index 000000000..2c6964e3e
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/widgetstack.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/widgets/wizard.png b/src/designer/src/components/formeditor/images/widgets/wizard.png
new file mode 100644
index 000000000..7c0e107ae
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/widgets/wizard.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/adjustsize.png b/src/designer/src/components/formeditor/images/win/adjustsize.png
new file mode 100644
index 000000000..3cda33371
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/adjustsize.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/back.png b/src/designer/src/components/formeditor/images/win/back.png
new file mode 100644
index 000000000..e58177f43
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/back.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/buddytool.png b/src/designer/src/components/formeditor/images/win/buddytool.png
new file mode 100644
index 000000000..4cd968bbf
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/buddytool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/down.png b/src/designer/src/components/formeditor/images/win/down.png
new file mode 100644
index 000000000..29d1d4439
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/down.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editbreaklayout.png b/src/designer/src/components/formeditor/images/win/editbreaklayout.png
new file mode 100644
index 000000000..07c5fae69
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editbreaklayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editcopy.png b/src/designer/src/components/formeditor/images/win/editcopy.png
new file mode 100644
index 000000000..1121b47d8
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editcopy.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editcut.png b/src/designer/src/components/formeditor/images/win/editcut.png
new file mode 100644
index 000000000..4b6c82c7a
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editcut.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editdelete.png b/src/designer/src/components/formeditor/images/win/editdelete.png
new file mode 100644
index 000000000..5a4251402
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editdelete.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editform.png b/src/designer/src/components/formeditor/images/win/editform.png
new file mode 100644
index 000000000..452fcd887
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editform.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editgrid.png b/src/designer/src/components/formeditor/images/win/editgrid.png
new file mode 100644
index 000000000..789bf7d96
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editgrid.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/edithlayout.png b/src/designer/src/components/formeditor/images/win/edithlayout.png
new file mode 100644
index 000000000..4dd3f0ce4
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/edithlayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/edithlayoutsplit.png b/src/designer/src/components/formeditor/images/win/edithlayoutsplit.png
new file mode 100644
index 000000000..2dcc69029
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/edithlayoutsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editlower.png b/src/designer/src/components/formeditor/images/win/editlower.png
new file mode 100644
index 000000000..ba630944c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editlower.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editpaste.png b/src/designer/src/components/formeditor/images/win/editpaste.png
new file mode 100644
index 000000000..ffab15aaf
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editpaste.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editraise.png b/src/designer/src/components/formeditor/images/win/editraise.png
new file mode 100644
index 000000000..bb8362c1f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editraise.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editvlayout.png b/src/designer/src/components/formeditor/images/win/editvlayout.png
new file mode 100644
index 000000000..7ad28fdea
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editvlayout.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/editvlayoutsplit.png b/src/designer/src/components/formeditor/images/win/editvlayoutsplit.png
new file mode 100644
index 000000000..720e18bb3
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/editvlayoutsplit.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/filenew.png b/src/designer/src/components/formeditor/images/win/filenew.png
new file mode 100644
index 000000000..af5d12214
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/filenew.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/fileopen.png b/src/designer/src/components/formeditor/images/win/fileopen.png
new file mode 100644
index 000000000..fc6f17e97
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/fileopen.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/filesave.png b/src/designer/src/components/formeditor/images/win/filesave.png
new file mode 100644
index 000000000..8feec99be
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/filesave.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/forward.png b/src/designer/src/components/formeditor/images/win/forward.png
new file mode 100644
index 000000000..34b91f09f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/forward.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/insertimage.png b/src/designer/src/components/formeditor/images/win/insertimage.png
new file mode 100644
index 000000000..cfab6375f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/insertimage.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/minus.png b/src/designer/src/components/formeditor/images/win/minus.png
new file mode 100644
index 000000000..c0dc274bb
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/minus.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/plus.png b/src/designer/src/components/formeditor/images/win/plus.png
new file mode 100644
index 000000000..ecf058941
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/plus.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/redo.png b/src/designer/src/components/formeditor/images/win/redo.png
new file mode 100644
index 000000000..686ad141c
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/redo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/resourceeditortool.png b/src/designer/src/components/formeditor/images/win/resourceeditortool.png
new file mode 100644
index 000000000..cc9cb5851
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/resourceeditortool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/signalslottool.png b/src/designer/src/components/formeditor/images/win/signalslottool.png
new file mode 100644
index 000000000..e80fd1caa
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/signalslottool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/simplifyrichtext.png b/src/designer/src/components/formeditor/images/win/simplifyrichtext.png
new file mode 100644
index 000000000..e251cf7b9
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/simplifyrichtext.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/tabordertool.png b/src/designer/src/components/formeditor/images/win/tabordertool.png
new file mode 100644
index 000000000..7e6e2de71
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/tabordertool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textanchor.png b/src/designer/src/components/formeditor/images/win/textanchor.png
new file mode 100644
index 000000000..1911ab0d5
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textanchor.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textbold.png b/src/designer/src/components/formeditor/images/win/textbold.png
new file mode 100644
index 000000000..9cbc7138b
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textbold.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textcenter.png b/src/designer/src/components/formeditor/images/win/textcenter.png
new file mode 100644
index 000000000..11efb4b85
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textcenter.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textitalic.png b/src/designer/src/components/formeditor/images/win/textitalic.png
new file mode 100644
index 000000000..b30ce14c1
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textitalic.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textjustify.png b/src/designer/src/components/formeditor/images/win/textjustify.png
new file mode 100644
index 000000000..9de0c8808
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textjustify.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textleft.png b/src/designer/src/components/formeditor/images/win/textleft.png
new file mode 100644
index 000000000..16f80bc32
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textleft.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textright.png b/src/designer/src/components/formeditor/images/win/textright.png
new file mode 100644
index 000000000..16872df62
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textright.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textsubscript.png b/src/designer/src/components/formeditor/images/win/textsubscript.png
new file mode 100644
index 000000000..d86347d83
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textsubscript.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textsuperscript.png b/src/designer/src/components/formeditor/images/win/textsuperscript.png
new file mode 100644
index 000000000..910996560
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textsuperscript.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/textunder.png b/src/designer/src/components/formeditor/images/win/textunder.png
new file mode 100644
index 000000000..c72eff53f
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/textunder.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/undo.png b/src/designer/src/components/formeditor/images/win/undo.png
new file mode 100644
index 000000000..c3b8c5136
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/undo.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/up.png b/src/designer/src/components/formeditor/images/win/up.png
new file mode 100644
index 000000000..e43731221
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/up.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/images/win/widgettool.png b/src/designer/src/components/formeditor/images/win/widgettool.png
new file mode 100644
index 000000000..a52224e06
--- /dev/null
+++ b/src/designer/src/components/formeditor/images/win/widgettool.png
Binary files differ
diff --git a/src/designer/src/components/formeditor/itemview_propertysheet.cpp b/src/designer/src/components/formeditor/itemview_propertysheet.cpp
new file mode 100644
index 000000000..e04c55d5a
--- /dev/null
+++ b/src/designer/src/components/formeditor/itemview_propertysheet.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemview_propertysheet.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QHeaderView>
+#include <QtCore/QDebug>
+
+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) {}
+
+ QDesignerPropertySheetExtension *m_sheet;
+ int m_id;
+};
+
+typedef QMap<int, Property> FakePropertyMap;
+
+struct ItemViewPropertySheetPrivate {
+ ItemViewPropertySheetPrivate(QDesignerFormEditorInterface *core,
+ QHeaderView *horizontalHeader,
+ QHeaderView *verticalHeader);
+
+ inline QStringList realPropertyNames();
+ inline QString fakePropertyName(const QString &prefix, const QString &realName);
+
+ // Maps index of fake property to index of real property in respective sheet
+ FakePropertyMap m_propertyIdMap;
+
+ // Maps name of fake property to name of real property
+ QHash<QString, QString> m_propertyNameMap;
+
+ 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(QDesignerFormEditorInterface *core,
+ QHeaderView *horizontalHeader,
+ QHeaderView *verticalHeader)
+{
+ if (horizontalHeader)
+ m_propertySheet.insert(horizontalHeader,
+ qt_extension<QDesignerPropertySheetExtension*>
+ (core->extensionManager(), horizontalHeader));
+ if (verticalHeader)
+ m_propertySheet.insert(verticalHeader,
+ qt_extension<QDesignerPropertySheetExtension*>
+ (core->extensionManager(), verticalHeader));
+}
+
+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(core(), treeViewObject->header(), 0))
+{
+ initHeaderProperties(treeViewObject->header(), QLatin1String("header"));
+}
+
+ItemViewPropertySheet::ItemViewPropertySheet(QTableView *tableViewObject, QObject *parent)
+ : QDesignerPropertySheet(tableViewObject, parent),
+ d(new ItemViewPropertySheetPrivate(core(),
+ tableViewObject->horizontalHeader(),
+ tableViewObject->verticalHeader()))
+{
+ initHeaderProperties(tableViewObject->horizontalHeader(), QLatin1String("horizontalHeader"));
+ initHeaderProperties(tableViewObject->verticalHeader(), QLatin1String("verticalHeader"));
+}
+
+ItemViewPropertySheet::~ItemViewPropertySheet()
+{
+ delete d;
+}
+
+void ItemViewPropertySheet::initHeaderProperties(QHeaderView *hv, const QString &prefix)
+{
+ QDesignerPropertySheetExtension *headerSheet = d->m_propertySheet.value(hv);
+ Q_ASSERT(headerSheet);
+ const QString headerGroupS = QLatin1String(headerGroup);
+ foreach (const QString &realPropertyName, d->realPropertyNames()) {
+ const int headerIndex = headerSheet->indexOf(realPropertyName);
+ Q_ASSERT(headerIndex != -1);
+ const QVariant defaultValue = realPropertyName == QLatin1String(visibleProperty) ?
+ QVariant(true) : headerSheet->property(headerIndex);
+ const QString fakePropertyName = d->fakePropertyName(prefix, realPropertyName);
+ const int fakeIndex = createFakeProperty(fakePropertyName, defaultValue);
+ d->m_propertyIdMap.insert(fakeIndex, Property(headerSheet, headerIndex));
+ setAttribute(fakeIndex, true);
+ setPropertyGroup(fakeIndex, headerGroupS);
+ }
+}
+
+/*!
+ 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
+{
+ const FakePropertyMap::const_iterator it = d->m_propertyIdMap.constFind(index);
+ if (it != d->m_propertyIdMap.constEnd())
+ return it.value().m_sheet->property(it.value().m_id);
+ return QDesignerPropertySheet::property(index);
+}
+
+void ItemViewPropertySheet::setProperty(int index, const QVariant &value)
+{
+ const FakePropertyMap::iterator it = d->m_propertyIdMap.find(index);
+ if (it != d->m_propertyIdMap.end()) {
+ it.value().m_sheet->setProperty(it.value().m_id, value);
+ } else {
+ QDesignerPropertySheet::setProperty(index, value);
+ }
+}
+
+void ItemViewPropertySheet::setChanged(int index, bool changed)
+{
+ const FakePropertyMap::iterator it = d->m_propertyIdMap.find(index);
+ if (it != d->m_propertyIdMap.end()) {
+ it.value().m_sheet->setChanged(it.value().m_id, changed);
+ } else {
+ QDesignerPropertySheet::setChanged(index, changed);
+ }
+}
+
+bool ItemViewPropertySheet::isChanged(int index) const
+{
+ const FakePropertyMap::const_iterator it = d->m_propertyIdMap.constFind(index);
+ if (it != d->m_propertyIdMap.constEnd())
+ return it.value().m_sheet->isChanged(it.value().m_id);
+ return QDesignerPropertySheet::isChanged(index);
+}
+
+bool ItemViewPropertySheet::hasReset(int index) const
+{
+ const FakePropertyMap::const_iterator it = d->m_propertyIdMap.constFind(index);
+ if (it != d->m_propertyIdMap.constEnd())
+ return it.value().m_sheet->hasReset(it.value().m_id);
+ return QDesignerPropertySheet::hasReset(index);
+}
+
+bool ItemViewPropertySheet::reset(int index)
+{
+ const FakePropertyMap::iterator it = d->m_propertyIdMap.find(index);
+ if (it != d->m_propertyIdMap.end()) {
+ QDesignerPropertySheetExtension *headerSheet = it.value().m_sheet;
+ const int headerIndex = it.value().m_id;
+ const bool resetRC = headerSheet->reset(headerIndex);
+ // Resetting for "visible" might fail and the stored default
+ // of the Widget database is "false" due to the widget not being
+ // visible at the time it was determined. Reset to "true" manually.
+ if (!resetRC && headerSheet->propertyName(headerIndex) == QLatin1String(visibleProperty)) {
+ headerSheet->setProperty(headerIndex, QVariant(true));
+ headerSheet->setChanged(headerIndex, false);
+ return true;
+ }
+ return resetRC;
+ } else {
+ return QDesignerPropertySheet::reset(index);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/formeditor/itemview_propertysheet.h b/src/designer/src/components/formeditor/itemview_propertysheet.h
new file mode 100644
index 000000000..59cf809c8
--- /dev/null
+++ b/src/designer/src/components/formeditor/itemview_propertysheet.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 {
+
+struct 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);
+
+ virtual void setChanged(int index, bool changed);
+ virtual bool isChanged(int index) const;
+
+ virtual bool hasReset(int index) const;
+ virtual bool reset(int index);
+
+private:
+ void initHeaderProperties(QHeaderView *hv, const QString &prefix);
+
+ 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/src/designer/src/components/formeditor/layout_propertysheet.cpp b/src/designer/src/components/formeditor/layout_propertysheet.cpp
new file mode 100644
index 000000000..34e51b178
--- /dev/null
+++ b/src/designer/src/components/formeditor/layout_propertysheet.cpp
@@ -0,0 +1,546 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/layout_propertysheet.h b/src/designer/src/components/formeditor/layout_propertysheet.h
new file mode 100644
index 000000000..72a59f876
--- /dev/null
+++ b/src/designer/src/components/formeditor/layout_propertysheet.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/line_propertysheet.cpp b/src/designer/src/components/formeditor/line_propertysheet.cpp
new file mode 100644
index 000000000..64699eaa5
--- /dev/null
+++ b/src/designer/src/components/formeditor/line_propertysheet.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/line_propertysheet.h b/src/designer/src/components/formeditor/line_propertysheet.h
new file mode 100644
index 000000000..ec1c098f3
--- /dev/null
+++ b/src/designer/src/components/formeditor/line_propertysheet.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/previewactiongroup.cpp b/src/designer/src/components/formeditor/previewactiongroup.cpp
new file mode 100644
index 000000000..607212c41
--- /dev/null
+++ b/src/designer/src/components/formeditor/previewactiongroup.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/previewactiongroup.h b/src/designer/src/components/formeditor/previewactiongroup.h
new file mode 100644
index 000000000..9ba65512b
--- /dev/null
+++ b/src/designer/src/components/formeditor/previewactiongroup.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/components/formeditor/qdesigner_resource.cpp b/src/designer/src/components/formeditor/qdesigner_resource.cpp
new file mode 100644
index 000000000..409a20e8d
--- /dev/null
+++ b/src/designer/src/components/formeditor/qdesigner_resource.cpp
@@ -0,0 +1,2475 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 "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/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;
+ const QDesignerLanguageExtension *m_lang;
+ 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_lang(qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core)),
+ m_saveRelative(true)
+{
+}
+
+static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory,
+ QString path, PropertySheetIconValue &icon,
+ const QDesignerLanguageExtension *lang = 0)
+{
+ if (lang == 0 || !lang->isLanguageResource(path))
+ path = QFileInfo(workingDirectory, path).absoluteFilePath();
+ icon.setPixmap(m, s, PropertySheetPixmapValue(path));
+}
+
+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()) {
+ if (m_lang != 0 && m_lang->isLanguageResource(dp->text())) {
+ pixmap.setPath(dp->text());
+ } else {
+ 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 QVariant::fromValue(pixmap);
+ }
+
+ case DomProperty::IconSet: {
+ PropertySheetIconValue icon;
+ DomResourceIcon *di = property->elementIconSet();
+ icon.setTheme(di->attributeTheme());
+ if (const int flags = iconStateFlags(di)) { // new, post 4.4 format
+ if (flags & NormalOff)
+ setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->elementNormalOff()->text(), icon, m_lang);
+ if (flags & NormalOn)
+ setIconPixmap(QIcon::Normal, QIcon::On, workingDirectory, di->elementNormalOn()->text(), icon, m_lang);
+ if (flags & DisabledOff)
+ setIconPixmap(QIcon::Disabled, QIcon::Off, workingDirectory, di->elementDisabledOff()->text(), icon, m_lang);
+ if (flags & DisabledOn)
+ setIconPixmap(QIcon::Disabled, QIcon::On, workingDirectory, di->elementDisabledOn()->text(), icon, m_lang);
+ if (flags & ActiveOff)
+ setIconPixmap(QIcon::Active, QIcon::Off, workingDirectory, di->elementActiveOff()->text(), icon, m_lang);
+ if (flags & ActiveOn)
+ setIconPixmap(QIcon::Active, QIcon::On, workingDirectory, di->elementActiveOn()->text(), icon, m_lang);
+ if (flags & SelectedOff)
+ setIconPixmap(QIcon::Selected, QIcon::Off, workingDirectory, di->elementSelectedOff()->text(), icon, m_lang);
+ if (flags & SelectedOn)
+ setIconPixmap(QIcon::Selected, QIcon::On, workingDirectory, di->elementSelectedOn()->text(), icon, m_lang);
+ } else {
+#ifdef OLD_RESOURCE_FORMAT
+ setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->text(), icon, m_lang);
+ if (di->hasAttributeResource())
+ m_loadedQrcFiles.insert(QFileInfo(workingDirectory, di->attributeResource()).absoluteFilePath(), false);
+#endif
+ }
+ return QVariant::fromValue(icon);
+ }
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const
+{
+ if (value.canConvert<PropertySheetPixmapValue>()) {
+ if (m_pixmapCache)
+ return m_pixmapCache->pixmap(qvariant_cast<PropertySheetPixmapValue>(value));
+ } else if (value.canConvert<PropertySheetIconValue>()) {
+ if (m_iconCache)
+ return m_iconCache->icon(qvariant_cast<PropertySheetIconValue>(value));
+ }
+ return value;
+}
+
+DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const
+{
+ DomProperty *p = new DomProperty;
+ if (value.canConvert<PropertySheetPixmapValue>()) {
+ 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 (value.canConvert<PropertySheetIconValue>()) {
+ const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value);
+ const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> pixmaps = icon.paths();
+ const QString theme = icon.theme();
+ if (!pixmaps.isEmpty() || !theme.isEmpty()) {
+ DomResourceIcon *ri = new DomResourceIcon;
+ if (!theme.isEmpty())
+ ri->setAttributeTheme(theme);
+ 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 (value.canConvert<PropertySheetPixmapValue>() || value.canConvert<PropertySheetIconValue>())
+ 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 QVariant::fromValue(strVal);
+}
+
+QVariant QDesignerTextBuilder::toNativeValue(const QVariant &value) const
+{
+ if (value.canConvert<PropertySheetStringValue>())
+ return QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(value).value());
+ return value;
+}
+
+DomProperty *QDesignerTextBuilder::saveText(const QVariant &value) const
+{
+ if (!value.canConvert<PropertySheetStringValue>() && !value.canConvert<QString>())
+ return 0;
+
+ DomProperty *property = new DomProperty();
+ DomString *domStr = new DomString();
+
+ if (value.canConvert<PropertySheetStringValue>()) {
+ PropertySheetStringValue str = qvariant_cast<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 = qvariant_cast<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;
+ }
+ QWidget *w = QEditorFormBuilder::load(dev, parentWidget);
+ if (w) // Store the class name as 'reset' value for the main container's object name.
+ w->setProperty("_q_classname", w->objectName());
+ return w;
+}
+
+bool QDesignerResource::saveRelative() const
+{
+ return m_resourceBuilder->isSaveRelative();
+}
+
+void QDesignerResource::setSaveRelative(bool relative)
+{
+ m_resourceBuilder->setSaveRelative(relative);
+}
+
+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 = w->findChild<QMenu*>(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 (sheetValue.canConvert<PropertySheetFlagValue>()) {
+ 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 (sheetValue.canConvert<PropertySheetEnumValue>()) {
+ 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 = QVariant::fromValue(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 = QVariant::fromValue(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 (v.canConvert<PropertySheetIconValue>()) {
+ defaultValue = QVariant(QVariant::Icon);
+ isDefault = (qvariant_cast<PropertySheetIconValue>(v) == PropertySheetIconValue());
+ } else if (v.canConvert<PropertySheetPixmapValue>()) {
+ defaultValue = QVariant(QVariant::Pixmap);
+ isDefault = (qvariant_cast<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue());
+ } else if (v.canConvert<PropertySheetStringValue>()) {
+ defaultValue = QVariant(QVariant::String);
+ isDefault = (qvariant_cast<PropertySheetStringValue>(v) == PropertySheetStringValue());
+ } else if (v.canConvert<PropertySheetKeySequenceValue>()) {
+ defaultValue = QVariant(QVariant::KeySequence);
+ isDefault = (qvariant_cast<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 = qvariant_cast<QWidgetList>(parentWidget->property("_q_widgetOrder"));
+ list.append(w);
+ parentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(list));
+ QList<QWidget *> zOrder = qvariant_cast<QWidgetList>(parentWidget->property("_q_zOrder"));
+ zOrder.append(w);
+ parentWidget->setProperty("_q_zOrder", QVariant::fromValue(zOrder));
+ }
+ } 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 (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 = layout->findChild<QLayout*>();
+ // 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;
+ }
+ return ui_item;
+}
+
+void QDesignerResource::createCustomWidgets(DomCustomWidgets *dom_custom_widgets)
+{
+ QSimpleResource::handleDomCustomWidgets(core(), dom_custom_widgets);
+}
+
+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 (const QString &widgetName, tabStops->elementTabStop()) {
+ if (QWidget *w = widget->findChild<QWidget*>(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;
+}
+
+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 = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon"))));
+ DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(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 (!qvariant_cast<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 (!qvariant_cast<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 = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon"))));
+ DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), QVariant::fromValue(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 (!qvariant_cast<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 (value.canConvert<PropertySheetFlagValue>()) {
+ const PropertySheetFlagValue f = qvariant_cast<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 (value.canConvert<PropertySheetEnumValue>()) {
+ const PropertySheetEnumValue e = qvariant_cast<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 (value.canConvert<PropertySheetStringValue>()) {
+ const PropertySheetStringValue strVal = qvariant_cast<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 (value.canConvert<PropertySheetKeySequenceValue>()) {
+ const PropertySheetKeySequenceValue keyVal = qvariant_cast<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;
+ m_formWindow->setProperty("_q_resourcepathchanged", QVariant(true));
+ } 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 (const 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/src/designer/src/components/formeditor/qdesigner_resource.h b/src/designer/src/components/formeditor/qdesigner_resource.h
new file mode 100644
index 000000000..b7113d162
--- /dev/null
+++ b/src/designer/src/components/formeditor/qdesigner_resource.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 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(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/src/designer/src/components/formeditor/qdesignerundostack.cpp b/src/designer/src/components/formeditor/qdesignerundostack.cpp
new file mode 100644
index 000000000..56bb04f9e
--- /dev/null
+++ b/src/designer/src/components/formeditor/qdesignerundostack.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesignerundostack.h"
+
+#include <QtGui/QUndoStack>
+#include <QtGui/QUndoCommand>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QDesignerUndoStack::QDesignerUndoStack(QObject *parent) :
+ QObject(parent),
+ m_undoStack(new QUndoStack),
+ m_fakeDirty(false)
+{
+ connect(m_undoStack, SIGNAL(indexChanged(int)), this, SIGNAL(changed()));
+}
+
+QDesignerUndoStack::~QDesignerUndoStack()
+{ // QUndoStack is managed by the QUndoGroup
+}
+
+void QDesignerUndoStack::push(QUndoCommand * cmd)
+{
+ m_undoStack->push(cmd);
+}
+
+void QDesignerUndoStack::beginMacro(const QString &text)
+{
+ m_undoStack->beginMacro(text);
+}
+
+void QDesignerUndoStack::endMacro()
+{
+ m_undoStack->endMacro();
+}
+
+int QDesignerUndoStack::index() const
+{
+ return m_undoStack->index();
+}
+
+const QUndoStack *QDesignerUndoStack::qundoStack() const
+{
+ return m_undoStack;
+}
+QUndoStack *QDesignerUndoStack::qundoStack()
+{
+ return m_undoStack;
+}
+
+bool QDesignerUndoStack::isDirty() const
+{
+ return m_fakeDirty || !m_undoStack->isClean();
+}
+
+void QDesignerUndoStack::setDirty(bool v)
+{
+ if (isDirty() == v)
+ return;
+ if (v) {
+ m_fakeDirty = true;
+ emit changed();
+ } else {
+ m_fakeDirty = false;
+ m_undoStack->setClean();
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/formeditor/qdesignerundostack.h b/src/designer/src/components/formeditor/qdesignerundostack.h
new file mode 100644
index 000000000..cabb4abdb
--- /dev/null
+++ b/src/designer/src/components/formeditor/qdesignerundostack.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNERUNDOSTACK_H
+#define QDESIGNERUNDOSTACK_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+class QUndoStack;
+class QUndoCommand;
+
+namespace qdesigner_internal {
+
+/* QDesignerUndoStack: A QUndoStack extended by a way of setting it to
+ * "dirty" indepently of commands (by modifications without commands
+ * such as resizing). Accomplished via bool m_fakeDirty flag. The
+ * lifecycle of the QUndoStack is managed by the QUndoGroup. */
+class QDesignerUndoStack : public QObject
+{
+ Q_DISABLE_COPY(QDesignerUndoStack)
+ Q_OBJECT
+public:
+ explicit QDesignerUndoStack(QObject *parent = 0);
+ virtual ~QDesignerUndoStack();
+
+ void push(QUndoCommand * cmd);
+ void beginMacro(const QString &text);
+ void endMacro();
+ int index() const;
+
+ const QUndoStack *qundoStack() const;
+ QUndoStack *qundoStack();
+
+ bool isDirty() const;
+
+signals:
+ void changed();
+
+public slots:
+ void setDirty(bool);
+
+private:
+ QUndoStack *m_undoStack;
+ bool m_fakeDirty;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNERUNDOSTACK_H
diff --git a/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp b/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp
new file mode 100644
index 000000000..49c49fa8e
--- /dev/null
+++ b/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.h b/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.h
new file mode 100644
index 000000000..76e3263f6
--- /dev/null
+++ b/src/designer/src/components/formeditor/qlayoutwidget_propertysheet.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/qmainwindow_container.cpp b/src/designer/src/components/formeditor/qmainwindow_container.cpp
new file mode 100644
index 000000000..d2664b418
--- /dev/null
+++ b/src/designer/src/components/formeditor/qmainwindow_container.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 += mw->layout()->findChildren<QLayout*>();
+ }
+ 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/src/designer/src/components/formeditor/qmainwindow_container.h b/src/designer/src/components/formeditor/qmainwindow_container.h
new file mode 100644
index 000000000..6151c97ff
--- /dev/null
+++ b/src/designer/src/components/formeditor/qmainwindow_container.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/qmdiarea_container.cpp b/src/designer/src/components/formeditor/qmdiarea_container.cpp
new file mode 100644
index 000000000..670d1d062
--- /dev/null
+++ b/src/designer/src/components/formeditor/qmdiarea_container.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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::LayoutDirectionAuto:
+ 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/src/designer/src/components/formeditor/qmdiarea_container.h b/src/designer/src/components/formeditor/qmdiarea_container.h
new file mode 100644
index 000000000..453e67109
--- /dev/null
+++ b/src/designer/src/components/formeditor/qmdiarea_container.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/qtbrushmanager.cpp b/src/designer/src/components/formeditor/qtbrushmanager.cpp
new file mode 100644
index 000000000..8cba8fa56
--- /dev/null
+++ b/src/designer/src/components/formeditor/qtbrushmanager.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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()
+{
+}
+
+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/src/designer/src/components/formeditor/qtbrushmanager.h b/src/designer/src/components/formeditor/qtbrushmanager.h
new file mode 100644
index 000000000..d490523c8
--- /dev/null
+++ b/src/designer/src/components/formeditor/qtbrushmanager.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+private:
+ QScopedPointer<QtBrushManagerPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QtBrushManager)
+ Q_DISABLE_COPY(QtBrushManager)
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/designer/src/components/formeditor/qwizard_container.cpp b/src/designer/src/components/formeditor/qwizard_container.cpp
new file mode 100644
index 000000000..d88bcf2f6
--- /dev/null
+++ b/src/designer/src/components/formeditor/qwizard_container.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwizard_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/src/designer/src/components/formeditor/qwizard_container.h b/src/designer/src/components/formeditor/qwizard_container.h
new file mode 100644
index 000000000..43a1e5f62
--- /dev/null
+++ b/src/designer/src/components/formeditor/qwizard_container.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/qworkspace_container.cpp b/src/designer/src/components/formeditor/qworkspace_container.cpp
new file mode 100644
index 000000000..ca7de1c56
--- /dev/null
+++ b/src/designer/src/components/formeditor/qworkspace_container.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/qworkspace_container.h b/src/designer/src/components/formeditor/qworkspace_container.h
new file mode 100644
index 000000000..f595044f4
--- /dev/null
+++ b/src/designer/src/components/formeditor/qworkspace_container.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/spacer_propertysheet.cpp b/src/designer/src/components/formeditor/spacer_propertysheet.cpp
new file mode 100644
index 000000000..6ea37c4d4
--- /dev/null
+++ b/src/designer/src/components/formeditor/spacer_propertysheet.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/spacer_propertysheet.h b/src/designer/src/components/formeditor/spacer_propertysheet.h
new file mode 100644
index 000000000..256e3fd71
--- /dev/null
+++ b/src/designer/src/components/formeditor/spacer_propertysheet.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/templateoptionspage.cpp b/src/designer/src/components/formeditor/templateoptionspage.cpp
new file mode 100644
index 000000000..d81abc12d
--- /dev/null
+++ b/src/designer/src/components/formeditor/templateoptionspage.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/templateoptionspage.h b/src/designer/src/components/formeditor/templateoptionspage.h
new file mode 100644
index 000000000..98d468caa
--- /dev/null
+++ b/src/designer/src/components/formeditor/templateoptionspage.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/templateoptionspage.ui b/src/designer/src/components/formeditor/templateoptionspage.ui
new file mode 100644
index 000000000..3427ffeb8
--- /dev/null
+++ b/src/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/src/designer/src/components/formeditor/tool_widgeteditor.cpp b/src/designer/src/components/formeditor/tool_widgeteditor.cpp
new file mode 100644
index 000000000..456967f59
--- /dev/null
+++ b/src/designer/src/components/formeditor/tool_widgeteditor.cpp
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/formeditor/tool_widgeteditor.h b/src/designer/src/components/formeditor/tool_widgeteditor.h
new file mode 100644
index 000000000..369c2fc14
--- /dev/null
+++ b/src/designer/src/components/formeditor/tool_widgeteditor.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/formeditor/widgetselection.cpp b/src/designer/src/components/formeditor/widgetselection.cpp
new file mode 100644
index 000000000..501859130
--- /dev/null
+++ b/src/designer/src/components/formeditor/widgetselection.cpp
@@ -0,0 +1,746 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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->formContainer()),
+ 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->formContainer()->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/src/designer/src/components/formeditor/widgetselection.h b/src/designer/src/components/formeditor/widgetselection.h
new file mode 100644
index 000000000..987bd4b51
--- /dev/null
+++ b/src/designer/src/components/formeditor/widgetselection.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/lib/lib.pro b/src/designer/src/components/lib/lib.pro
new file mode 100644
index 000000000..50a8b00fa
--- /dev/null
+++ b/src/designer/src/components/lib/lib.pro
@@ -0,0 +1,77 @@
+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, "", true)|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 += . .. \
+ $$PWD/../../lib/components \
+ $$PWD/../../lib/sdk \
+ $$PWD/../../lib/extension \
+ $$PWD/../../lib/uilib \
+ $$PWD/../../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|win32-g++* {
+ QMAKE_PKGCONFIG_REQUIRES = QtCore QtDesigner QtGui QtXml
+ contains(QT_CONFIG, script): QMAKE_PKGCONFIG_REQUIRES += QtScript
+}
+
+target.path=$$[QT_INSTALL_LIBS]
+INSTALLS += target
+win32 {
+ dlltarget.path=$$[QT_INSTALL_BINS]
+ INSTALLS += dlltarget
+}
diff --git a/src/designer/src/components/lib/lib_pch.h b/src/designer/src/components/lib/lib_pch.h
new file mode 100644
index 000000000..7f2765a79
--- /dev/null
+++ b/src/designer/src/components/lib/lib_pch.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/QtDesigner>
+#include <QtDesigner/QExtensionManager>
diff --git a/src/designer/src/components/lib/qdesigner_components.cpp b/src/designer/src/components/lib/qdesigner_components.cpp
new file mode 100644
index 000000000..9b7457f46
--- /dev/null
+++ b/src/designer/src/components/lib/qdesigner_components.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/components/objectinspector/objectinspector.cpp b/src/designer/src/components/objectinspector/objectinspector.cpp
new file mode 100644
index 000000000..8bcd49e15
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspector.cpp
@@ -0,0 +1,835 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/objectinspector/objectinspector.h b/src/designer/src/components/objectinspector/objectinspector.h
new file mode 100644
index 000000000..ebf4da2ce
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspector.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/objectinspector/objectinspector.pri b/src/designer/src/components/objectinspector/objectinspector.pri
new file mode 100644
index 000000000..565f78bdc
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspector.pri
@@ -0,0 +1,16 @@
+# --- The Find widget is also linked into the designer_shared library.
+# Avoid conflict when linking statically
+contains(CONFIG, static) {
+ INCLUDEPATH *= $$QT_SOURCE_TREE/tools/shared/findwidget
+} else {
+ include(../../../../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/src/designer/src/components/objectinspector/objectinspector_global.h b/src/designer/src/components/objectinspector/objectinspector_global.h
new file mode 100644
index 000000000..08ddf6e68
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspector_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/objectinspector/objectinspectormodel.cpp b/src/designer/src/components/objectinspector/objectinspectormodel.cpp
new file mode 100644
index 000000000..20f0ff18f
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspectormodel.cpp
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = QVariant::fromValue(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/src/designer/src/components/objectinspector/objectinspectormodel_p.h b/src/designer/src/components/objectinspector/objectinspectormodel_p.h
new file mode 100644
index 000000000..499a99afb
--- /dev/null
+++ b/src/designer/src/components/objectinspector/objectinspectormodel_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/components/propertyeditor/brushpropertymanager.cpp b/src/designer/src/components/propertyeditor/brushpropertymanager.cpp
new file mode 100644
index 000000000..973de63bb
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/brushpropertymanager.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+}
+
+
+typedef QMap<int, QIcon> EnumIndexIconMap;
+
+static void clearBrushIcons();
+Q_GLOBAL_STATIC_WITH_INITIALIZER(EnumIndexIconMap, brushIcons, qAddPostRoutine(clearBrushIcons))
+
+static void clearBrushIcons()
+{
+ brushIcons()->clear();
+}
+
+const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
+{
+ // Create a map of icons for the brush style editor
+ if (brushIcons()->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);
+ brushIcons()->insert(i, QtPropertyBrowserUtils::brushValueIcon(brush));
+ }
+ }
+ return *(brushIcons());
+}
+
+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"), QVariant::fromValue(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/src/designer/src/components/propertyeditor/brushpropertymanager.h b/src/designer/src/components/propertyeditor/brushpropertymanager.h
new file mode 100644
index 000000000..5c008e2c4
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/brushpropertymanager.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/designerpropertymanager.cpp b/src/designer/src/components/propertyeditor/designerpropertymanager.cpp
new file mode 100644
index 000000000..78fb9aaf0
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/designerpropertymanager.cpp
@@ -0,0 +1,2836 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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";
+static const char *themeAttributeC = "theme";
+
+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); }
+
+ void setIconThemeModeEnabled(bool enable);
+
+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;
+ IconThemeEditor *m_themeEditor;
+ bool m_iconThemeModeEnabled;
+ 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_themeEditor(new IconThemeEditor(this, false)),
+ m_iconThemeModeEnabled(false),
+ 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_themeEditor->setVisible(false);
+ m_button->setVisible(false);
+
+ m_layout->addWidget(m_editor);
+ m_layout->addWidget(m_themeEditor);
+ 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_themeEditor, SIGNAL(edited(QString)), this, SIGNAL(textChanged(QString)));
+ connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ setFocusProxy(m_editor);
+
+ m_menu->addAction(m_resourceAction);
+ m_menu->addAction(m_fileAction);
+}
+
+void TextEditor::setSpacing(int spacing)
+{
+ m_layout->setSpacing(spacing);
+}
+
+void TextEditor::setIconThemeModeEnabled(bool enable)
+{
+ if (m_iconThemeModeEnabled == enable)
+ return; // nothing changes
+ m_iconThemeModeEnabled = enable;
+ m_editor->setVisible(!enable);
+ m_themeEditor->setVisible(enable);
+ if (enable) {
+ m_themeEditor->setTheme(m_editor->text());
+ setFocusProxy(m_themeEditor);
+ } else {
+ m_editor->setText(m_themeEditor->theme());
+ setFocusProxy(m_editor);
+ }
+}
+
+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)
+{
+ if (m_iconThemeModeEnabled)
+ m_themeEditor->setTheme(text);
+ else
+ 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.remove(0, 4);
+ // returns ':/file'
+ QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this);
+ if (newPath.startsWith(QLatin1Char(':')))
+ newPath.remove(0, 1);
+ 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 = QUrl::fromLocalFile(newPath).toString();
+ m_editor->setText(newText);
+ emit textChanged(newText);
+}
+
+// ------------ ThemeInputDialog
+
+class IconThemeDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ static QString getTheme(QWidget *parent, const QString &theme, bool *ok);
+private:
+ IconThemeDialog(QWidget *parent);
+ IconThemeEditor *m_editor;
+};
+
+IconThemeDialog::IconThemeDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ setWindowTitle(tr("Set Icon From Theme"));
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QLabel *label = new QLabel(tr("Input icon name from the current theme:"), this);
+ m_editor = new IconThemeEditor(this);
+ QDialogButtonBox *buttons = new QDialogButtonBox(this);
+ buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ layout->addWidget(label);
+ layout->addWidget(m_editor);
+ layout->addWidget(buttons);
+
+ connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+QString IconThemeDialog::getTheme(QWidget *parent, const QString &theme, bool *ok)
+{
+ IconThemeDialog dlg(parent);
+ dlg.m_editor->setTheme(theme);
+ if (dlg.exec() == QDialog::Accepted) {
+ *ok = true;
+ return dlg.m_editor->theme();
+ }
+ *ok = false;
+ return QString();
+}
+
+// ------------ PixmapEditor
+class PixmapEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+
+ void setSpacing(int spacing);
+ void setPixmapCache(DesignerPixmapCache *cache);
+ void setIconThemeModeEnabled(bool enabled);
+public slots:
+ void setPath(const QString &path);
+ void setTheme(const QString &theme);
+ void setDefaultPixmap(const QPixmap &pixmap);
+
+signals:
+ void pathChanged(const QString &path);
+ void themeChanged(const QString &theme);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+
+private slots:
+ void defaultActionActivated();
+ void resourceActionActivated();
+ void fileActionActivated();
+ void themeActionActivated();
+ void copyActionActivated();
+ void pasteActionActivated();
+ void clipboardDataChanged();
+private:
+ void updateLabels();
+ bool m_iconThemeModeEnabled;
+ QDesignerFormEditorInterface *m_core;
+ QLabel *m_pixmapLabel;
+ QLabel *m_pathLabel;
+ QToolButton *m_button;
+ QAction *m_resourceAction;
+ QAction *m_fileAction;
+ QAction *m_themeAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+ QHBoxLayout *m_layout;
+ QPixmap m_defaultPixmap;
+ QString m_path;
+ QString m_theme;
+ DesignerPixmapCache *m_pixmapCache;
+};
+
+PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_iconThemeModeEnabled(false),
+ 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_themeAction(new QAction(tr("Set Icon From Theme..."), 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));
+ m_themeAction->setVisible(false);
+
+ QMenu *menu = new QMenu(this);
+ menu->addAction(m_resourceAction);
+ menu->addAction(m_fileAction);
+ menu->addAction(m_themeAction);
+
+ 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_themeAction, SIGNAL(triggered()), this, SLOT(themeActionActivated()));
+ 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::setIconThemeModeEnabled(bool enabled)
+{
+ if (m_iconThemeModeEnabled == enabled)
+ return;
+ m_iconThemeModeEnabled = enabled;
+ m_themeAction->setVisible(enabled);
+}
+
+void PixmapEditor::setSpacing(int spacing)
+{
+ m_layout->setSpacing(spacing);
+}
+
+void PixmapEditor::setPath(const QString &path)
+{
+ m_path = path;
+ updateLabels();
+}
+
+void PixmapEditor::setTheme(const QString &theme)
+{
+ m_theme = theme;
+ updateLabels();
+}
+
+void PixmapEditor::updateLabels()
+{
+ if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) {
+ m_pixmapLabel->setPixmap(QIcon::fromTheme(m_theme).pixmap(16, 16));
+ m_pathLabel->setText(tr("[Theme] %1").arg(m_theme));
+ m_copyAction->setEnabled(true);
+ } else {
+ if (m_path.isEmpty()) {
+ m_pathLabel->setText(m_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(m_path))).pixmap(16, 16));
+ m_copyAction->setEnabled(true);
+ }
+ }
+}
+
+void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap)
+{
+ m_defaultPixmap = QIcon(pixmap).pixmap(16, 16);
+ const bool hasThemeIcon = m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme);
+ if (!hasThemeIcon && 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()
+{
+ if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme)) {
+ themeActionActivated();
+ return;
+ }
+ // 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) {
+ setTheme(QString());
+ 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) {
+ setTheme(QString());
+ setPath(newPath);
+ emit pathChanged(newPath);
+ }
+}
+
+void PixmapEditor::themeActionActivated()
+{
+ bool ok;
+ const QString newTheme = IconThemeDialog::getTheme(this, m_theme, &ok);
+ if (ok && newTheme != m_theme) {
+ setTheme(newTheme);
+ setPath(QString());
+ emit themeChanged(newTheme);
+ }
+}
+
+void PixmapEditor::copyActionActivated()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(m_theme))
+ clipboard->setText(m_theme);
+ else
+ 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);
+ if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(text)) {
+ setTheme(text);
+ setPath(QString());
+ emit themeChanged(text);
+ } else {
+ setPath(text);
+ setTheme(QString());
+ 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;
+ v.setValue(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(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(newValue));
+ } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(property, 0)) {
+ QtVariantProperty *iconProperty = variantProperty(iProperty);
+ PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(iconProperty->value());
+ QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> >::ConstIterator itState = m_iconSubPropertyToState.constFind(property);
+ if (itState != m_iconSubPropertyToState.constEnd()) {
+ QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property);
+ icon.setPixmap(pair.first, pair.second, qvariant_cast<PropertySheetPixmapValue>(value));
+ } else { // must be theme property
+ icon.setTheme(value.toString());
+ }
+ QtProperty *origSourceOfChange = m_sourceOfChange;
+ if (!origSourceOfChange)
+ m_sourceOfChange = property;
+ iconProperty->setValue(QVariant::fromValue(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)) {
+ if (m_propertyToTheme.value(iconProperty) == property) {
+ m_propertyToTheme.remove(iconProperty);
+ } else {
+ 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));
+ list.append(QLatin1String(themeAttributeC));
+ } 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 (attribute == QLatin1String(themeAttributeC))
+ return QVariant::Bool;
+ }
+ 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;
+ v.setValue(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(themeAttributeC)) {
+ const PropertyBoolMap::const_iterator it = m_stringThemeAttributes.constFind(prop);
+ if (it != m_stringThemeAttributes.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 = qvariant_cast<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;
+ v.setValue(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(themeAttributeC) && m_stringThemeAttributes.contains(property)) {
+ if (value.userType() != QVariant::Bool)
+ return;
+
+ const PropertyBoolMap::iterator it = m_stringThemeAttributes.find(property);
+ const bool oldValue = it.value();
+
+ const bool newValue = value.toBool();
+
+ 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 = qvariant_cast<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;
+ v.setValue(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 = qvariant_cast<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 = QVariant::fromValue(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 = qvariant_cast<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 = QVariant::fromValue(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 icon = m_iconValues.value(const_cast<QtProperty *>(property));
+ const QString theme = icon.theme();
+ if (!theme.isEmpty() && QIcon::hasThemeIcon(theme))
+ return tr("[Theme] %1").arg(theme);
+ const PropertySheetIconValue::ModeStateToPixmapMap paths = icon.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() : qvariant_cast<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 qvariant_cast<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, QVariant::fromValue(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, QVariant::fromValue(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 if (m_stringThemeAttributes.value(const_cast<QtProperty *>(property), false)) {
+ return QIcon::fromTheme(value(property).toString());
+ } 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 QVariant::fromValue(m_iconValues.value(const_cast<QtProperty *>(property)));
+ if (m_pixmapValues.contains(const_cast<QtProperty *>(property)))
+ return QVariant::fromValue(m_pixmapValues.value(const_cast<QtProperty *>(property)));
+ if (m_stringValues.contains(const_cast<QtProperty *>(property)))
+ return QVariant::fromValue(m_stringValues.value(const_cast<QtProperty *>(property)));
+ if (m_keySequenceValues.contains(const_cast<QtProperty *>(property)))
+ return QVariant::fromValue(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 = qvariant_cast<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, QVariant::fromValue(v));
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_keySequenceValues.contains(property)) {
+ if (value.userType() != designerKeySequenceTypeId())
+ return;
+
+ const PropertySheetKeySequenceValue v = qvariant_cast<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, QVariant::fromValue(v));
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_paletteValues.contains(property)) {
+ if (value.type() != QVariant::Palette && !value.canConvert(QVariant::Palette))
+ return;
+
+ QPalette p = qvariant_cast<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 = qvariant_cast<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(QVariant::fromValue(iconPaths.value(pair)));
+ subProperty->setAttribute(QLatin1String(defaultResourceAttributeC),
+ defaultIcon.pixmap(16, 16, pair.first, pair.second));
+ }
+ QtVariantProperty *themeSubProperty = variantProperty(m_propertyToTheme.value(property));
+ if (themeSubProperty) {
+ const QString theme = icon.theme();
+ themeSubProperty->setModified(!theme.isEmpty());
+ themeSubProperty->setValue(theme);
+ }
+
+ emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(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 = qvariant_cast<PropertySheetPixmapValue>(value);
+
+ const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(property);
+ if (pixmap == oldPixmap)
+ return;
+
+ m_pixmapValues[property] = pixmap;
+
+ emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(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(qvariant_cast<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value());
+ else if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId())
+ property->setToolTip(qvariant_cast<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();
+ m_stringThemeAttributes[property] = false;
+ 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();
+
+ QtVariantProperty *themeProp = addProperty(QVariant::String, tr("Theme"));
+ themeProp->setAttribute(QLatin1String(themeAttributeC), true);
+ m_iconSubPropertyToProperty[themeProp] = property;
+ m_propertyToTheme[property] = themeProp;
+ m_resetMap[themeProp] = true;
+ property->addSubProperty(themeProp);
+
+ 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();
+ m_stringThemeAttributes[property] = false;
+
+ 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_commentToString.remove(stringComment);
+ }
+
+ QtProperty *stringTranslatable = m_stringToTranslatable.value(property);
+ if (stringTranslatable) {
+ delete stringTranslatable;
+ m_translatableToString.remove(stringTranslatable);
+ }
+
+ QtProperty *stringDisambiguation = m_stringToDisambiguation.value(property);
+ if (stringDisambiguation) {
+ delete stringDisambiguation;
+ m_disambiguationToString.remove(stringDisambiguation);
+ }
+
+ QtProperty *keySequenceComment = m_keySequenceToComment.value(property);
+ if (keySequenceComment) {
+ delete keySequenceComment;
+ m_commentToKeySequence.remove(keySequenceComment);
+ }
+
+ QtProperty *keySequenceTranslatable = m_keySequenceToTranslatable.value(property);
+ if (keySequenceTranslatable) {
+ delete keySequenceTranslatable;
+ m_translatableToKeySequence.remove(keySequenceTranslatable);
+ }
+
+ QtProperty *keySequenceDisambiguation = m_keySequenceToDisambiguation.value(property);
+ if (keySequenceDisambiguation) {
+ delete keySequenceDisambiguation;
+ m_disambiguationToKeySequence.remove(keySequenceDisambiguation);
+ }
+
+ QtProperty *iconTheme = m_propertyToTheme.value(property);
+ if (iconTheme) {
+ delete iconTheme;
+ m_iconSubPropertyToProperty.remove(iconTheme);
+ }
+
+ 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)
+{
+ QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property);
+ if (!iconProperty)
+ return false;
+
+ if (m_pixmapValues.contains(property)) {
+ QtVariantProperty *pixmapProperty = variantProperty(property);
+ pixmapProperty->setValue(QVariant::fromValue(PropertySheetPixmapValue()));
+ return true;
+ } else if (m_propertyToTheme.contains(iconProperty)) {
+ QtVariantProperty *themeProperty = variantProperty(property);
+ themeProperty->setValue(QString());
+ return true;
+ }
+ return false;
+}
+
+// -------- 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);
+ }
+ if (attribute == QLatin1String(themeAttributeC)) {
+ const bool themeEnabled = value.toBool();
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setIconThemeModeEnabled, themeEnabled);
+ }
+ } 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(qvariant_cast<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()) {
+ PropertySheetIconValue iconValue = qvariant_cast<PropertySheetIconValue>(value);
+ const QString theme = iconValue.theme();
+ applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setTheme, iconValue.theme());
+ applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, iconValue.pixmap(QIcon::Normal, QIcon::Off).path());
+ } else if (type == DesignerPropertyManager::designerPixmapTypeId()) {
+ applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qvariant_cast<PropertySheetPixmapValue>(value).path());
+ } else if (type == DesignerPropertyManager::designerStringTypeId()) {
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qvariant_cast<PropertySheetStringValue>(value).value());
+ } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) {
+ applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qvariant_cast<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));
+ const bool themeEnabled = manager->attributeValue(property, QLatin1String(themeAttributeC)).toBool();
+ ed->setIconThemeModeEnabled(themeEnabled);
+ 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(QString)), this, SLOT(slotPixmapChanged(QString)));
+ editor = ed;
+ } else if (type == DesignerPropertyManager::designerIconTypeId()) {
+ PixmapEditor *ed = new PixmapEditor(m_core, parent);
+ ed->setPixmapCache(m_fwb->pixmapCache());
+ ed->setIconThemeModeEnabled(true);
+ PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(manager->value(property));
+ ed->setTheme(value.theme());
+ 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(QString)), this, SLOT(slotIconChanged(QString)));
+ connect(ed, SIGNAL(themeChanged(QString)), this, SLOT(slotIconThemeChanged(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, qvariant_cast<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(qvariant_cast<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 = qvariant_cast<PropertySheetStringValue>(val);
+ strVal.setValue(value);
+ // Disable translation if no translation subproperties exist.
+ if (varProp->subProperties().empty())
+ strVal.setTranslatable(false);
+ val = QVariant::fromValue(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 = qvariant_cast<PropertySheetKeySequenceValue>(val);
+ keyVal.setValue(value);
+ val = QVariant::fromValue(keyVal);
+ } else {
+ val = QVariant::fromValue(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()), QVariant::fromValue(value));
+}
+
+void DesignerEditorFactory::slotPixmapChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToPixmapProperty, qobject_cast<QWidget *>(sender()),
+ QVariant::fromValue(PropertySheetPixmapValue(value)));
+}
+
+void DesignerEditorFactory::slotIconChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()),
+ QVariant::fromValue(PropertySheetIconValue(PropertySheetPixmapValue(value))));
+}
+
+void DesignerEditorFactory::slotIconThemeChanged(const QString &value)
+{
+ PropertySheetIconValue icon;
+ icon.setTheme(value);
+ updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()),
+ QVariant::fromValue(icon));
+}
+
+void DesignerEditorFactory::slotStringListChanged(const QStringList &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), QVariant::fromValue(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/src/designer/src/components/propertyeditor/designerpropertymanager.h b/src/designer/src/components/propertyeditor/designerpropertymanager.h
new file mode 100644
index 000000000..4f4bb3c17
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/designerpropertymanager.h
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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;
+ PropertyToPropertyMap m_propertyToTheme;
+
+ 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;
+ PropertyBoolMap m_stringThemeAttributes;
+
+ 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 slotIconThemeChanged(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/src/designer/src/components/propertyeditor/fontmapping.xml b/src/designer/src/components/propertyeditor/fontmapping.xml
new file mode 100644
index 000000000..cbd68b8db
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/fontmapping.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/propertyeditor/fontpropertymanager.cpp b/src/designer/src/components/propertyeditor/fontpropertymanager.cpp
new file mode 100644
index 000000000..d04bfe6e2
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/fontpropertymanager.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = qvariant_cast<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);
+ v.setValue(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 = qvariant_cast<QFont>(fontProperty->value());
+ const QFont::StyleStrategy oldValue = font.styleStrategy();
+ if (newValue == oldValue)
+ return Unchanged;
+
+ font.setStyleStrategy(newValue);
+ fontProperty->setValue(QVariant::fromValue(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 = qvariant_cast<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 = qvariant_cast<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/src/designer/src/components/propertyeditor/fontpropertymanager.h b/src/designer/src/components/propertyeditor/fontpropertymanager.h
new file mode 100644
index 000000000..2154186b7
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/fontpropertymanager.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp b/src/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp
new file mode 100644
index 000000000..32277a0ba
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/propertyeditor/newdynamicpropertydialog.h b/src/designer/src/components/propertyeditor/newdynamicpropertydialog.h
new file mode 100644
index 000000000..7c3966a43
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/newdynamicpropertydialog.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/newdynamicpropertydialog.ui b/src/designer/src/components/propertyeditor/newdynamicpropertydialog.ui
new file mode 100644
index 000000000..2aa91f3e9
--- /dev/null
+++ b/src/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/src/designer/src/components/propertyeditor/paletteeditor.cpp b/src/designer/src/components/propertyeditor/paletteeditor.cpp
new file mode 100644
index 000000000..55a6da5cb
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/paletteeditor.cpp
@@ -0,0 +1,616 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(QPalette)),
+ this, SLOT(paletteChanged(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 = qvariant_cast<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 = qvariant_cast<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(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 = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
+ RoleEditor *editor = static_cast<RoleEditor *>(ed);
+ editor->setEdited(mask);
+ const QString colorName = qvariant_cast<QString>(index.model()->data(index, Qt::DisplayRole));
+ editor->setLabel(colorName);
+ } else {
+ const QBrush br = qvariant_cast<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 = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
+ if (index.column() == 0 && mask) {
+ option.font.setBold(true);
+ }
+ QBrush br = qvariant_cast<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/src/designer/src/components/propertyeditor/paletteeditor.h b/src/designer/src/components/propertyeditor/paletteeditor.h
new file mode 100644
index 000000000..9caed1965
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/paletteeditor.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/paletteeditor.ui b/src/designer/src/components/propertyeditor/paletteeditor.ui
new file mode 100644
index 000000000..12d27127b
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/paletteeditor.ui
@@ -0,0 +1,264 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/propertyeditor/paletteeditorbutton.cpp b/src/designer/src/components/propertyeditor/paletteeditorbutton.cpp
new file mode 100644
index 000000000..b716de1e1
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/paletteeditorbutton.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/propertyeditor/paletteeditorbutton.h b/src/designer/src/components/propertyeditor/paletteeditorbutton.h
new file mode 100644
index 000000000..567605a19
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/paletteeditorbutton.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/previewframe.cpp b/src/designer/src/components/propertyeditor/previewframe.cpp
new file mode 100644
index 000000000..5e426c9c7
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/previewframe.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewframe.h"
+#include "previewwidget.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtGui/QPainter>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QPaintEvent>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ 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));
+ //: Palette editor background
+ p.drawText(0, height() / 2, width(), height(), Qt::AlignHCenter,
+ QCoreApplication::translate("qdesigner_internal::PreviewMdiArea", "The moose in the noose\nate the goose who was loose."));
+ return true;
+ }
+
+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/src/designer/src/components/propertyeditor/previewframe.h b/src/designer/src/components/propertyeditor/previewframe.h
new file mode 100644
index 000000000..567fd7f7a
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/previewframe.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/previewwidget.cpp b/src/designer/src/components/propertyeditor/previewwidget.cpp
new file mode 100644
index 000000000..8dec3ffff
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/previewwidget.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/propertyeditor/previewwidget.h b/src/designer/src/components/propertyeditor/previewwidget.h
new file mode 100644
index 000000000..4b014db8a
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/previewwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/previewwidget.ui b/src/designer/src/components/propertyeditor/previewwidget.ui
new file mode 100644
index 000000000..a5f2a1eee
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/previewwidget.ui
@@ -0,0 +1,238 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/propertyeditor/propertyeditor.cpp b/src/designer/src/components/propertyeditor/propertyeditor.cpp
new file mode 100644
index 000000000..9f298d0a4
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/propertyeditor.cpp
@@ -0,0 +1,1294 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtGui/QPainter>
+
+#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";
+static const char *SplitterPositionKeyC = "SplitterPosition";
+
+enum SettingsView { TreeView, ButtonView };
+
+QT_BEGIN_NAMESPACE
+
+// ---------------------------------------------------------------------------------
+
+namespace qdesigner_internal {
+
+// ----------- ElidingLabel
+// QLabel does not support text eliding so we need a helper class
+
+class ElidingLabel : public QWidget
+{
+public:
+ ElidingLabel(const QString &text = QString(), QWidget *parent = 0)
+ : QWidget(parent),
+ m_text(text),
+ m_mode(Qt::ElideRight) {
+ setContentsMargins(3, 2, 3, 2);
+ }
+ QSize sizeHint() const;
+ void paintEvent(QPaintEvent *e);
+ void setText(const QString &text) {
+ m_text = text;
+ updateGeometry();
+ }
+ void setElidemode(Qt::TextElideMode mode) {
+ m_mode = mode;
+ updateGeometry();
+ }
+private:
+ QString m_text;
+ Qt::TextElideMode m_mode;
+};
+
+QSize ElidingLabel::sizeHint() const
+{
+ QSize size = fontMetrics().boundingRect(m_text).size();
+ size += QSize(contentsMargins().left() + contentsMargins().right(),
+ contentsMargins().top() + contentsMargins().bottom());
+ return size;
+}
+
+void ElidingLabel::paintEvent(QPaintEvent *) {
+ QPainter painter(this);
+ painter.setPen(QColor(0, 0, 0, 60));
+ painter.setBrush(QColor(255, 255, 255, 40));
+ painter.drawRect(rect().adjusted(0, 0, -1, -1));
+ painter.setPen(palette().windowText().color());
+ painter.drawText(contentsRect(), Qt::AlignLeft,
+ fontMetrics().elidedText(m_text, Qt::ElideRight, width(), 0));
+}
+
+
+// ----------- 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)
+ qDeleteAll(property->subProperties());
+}
+
+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 ElidingLabel),
+ 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());
+ const int darknessFactor = 250;
+ for (int i = 0; i < colors.count(); i++) {
+ QColor c = colors.at(i);
+ m_colors.push_back(qMakePair(c, c.darker(darknessFactor)));
+ }
+ QColor dynamicColor(191, 207, 255);
+ QColor layoutColor(255, 191, 191);
+ m_dynamicColor = qMakePair(dynamicColor, dynamicColor.darker(darknessFactor));
+ m_layoutColor = qMakePair(layoutColor, layoutColor.darker(darknessFactor));
+
+ 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*)));
+
+ // 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 >= 0x04FF00
+ configureMenu->addSeparator();
+ configureMenu->addAction(m_treeAction);
+ configureMenu->addAction(m_buttonAction);
+#endif
+ // Assemble toolbar
+ QToolBar *toolBar = new QToolBar;
+ 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_classLabel);
+ layout->addSpacerItem(new QSpacerItem(0,1));
+ 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();
+ const int splitterPosition = settings->value(QLatin1String(SplitterPositionKeyC), 150).toInt();
+ settings->endGroup();
+ // Apply settings
+ m_sortingAction->setChecked(m_sorting);
+ m_coloringAction->setChecked(m_coloring);
+ m_treeBrowser->setSplitterPosition(splitterPosition);
+#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->setValue(QLatin1String(SplitterPositionKeyC), m_treeBrowser->splitterPosition());
+ 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);
+ }
+
+ m_classLabel->setVisible(!objectName.isEmpty() || !className.isEmpty());
+ m_classLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ QString classLabelText;
+ if (!objectName.isEmpty())
+ classLabelText += objectName + QLatin1String(" : ");
+ 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 (value.canConvert<PropertySheetFlagValue>()) {
+ if (m_strings.m_alignmentProperties.contains(propertyName))
+ return DesignerPropertyManager::designerAlignmentTypeId();
+ return DesignerPropertyManager::designerFlagTypeId();
+ }
+ if (value.canConvert<PropertySheetEnumValue>())
+ 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;
+ v.setValue(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;
+ v.setValue(e);
+ emitPropertyValueChanged(property->propertyName(), v, true);
+ return;
+ }
+
+ emitPropertyValueChanged(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/src/designer/src/components/propertyeditor/propertyeditor.h b/src/designer/src/components/propertyeditor/propertyeditor.h
new file mode 100644
index 000000000..7278a3de9
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/propertyeditor.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+namespace qdesigner_internal {
+
+class StringProperty;
+class DesignerPropertyManager;
+class DesignerEditorFactory;
+class FilterWidget;
+class ElidingLabel;
+
+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;
+ ElidingLabel *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/src/designer/src/components/propertyeditor/propertyeditor.pri b/src/designer/src/components/propertyeditor/propertyeditor.pri
new file mode 100644
index 000000000..bb1afdb94
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/propertyeditor.pri
@@ -0,0 +1,52 @@
+#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
+
+# --- Property browser is also linked into the designer_shared library.
+# Avoid conflict when linking statically
+contains(CONFIG, static) {
+ INCLUDEPATH *= $$QT_SOURCE_TREE/tools/shared/qtpropertybrowser
+ INCLUDEPATH *= $$QT_SOURCE_TREE/tools/shared/qtgradienteditor
+} else {
+ include(../../../../shared/qtpropertybrowser/qtpropertybrowser.pri)
+ include(../../../../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/qlonglongvalidator.h
+
+SOURCES += $$PWD/qlonglongvalidator.cpp
+
+RESOURCES += $$PWD/propertyeditor.qrc
diff --git a/src/designer/src/components/propertyeditor/propertyeditor.qrc b/src/designer/src/components/propertyeditor/propertyeditor.qrc
new file mode 100644
index 000000000..68008eca8
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/propertyeditor.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/propertyeditor">
+ <file>fontmapping.xml</file>
+ </qresource>
+</RCC>
diff --git a/src/designer/src/components/propertyeditor/propertyeditor_global.h b/src/designer/src/components/propertyeditor/propertyeditor_global.h
new file mode 100644
index 000000000..f173392f5
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/propertyeditor_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/qlonglongvalidator.cpp b/src/designer/src/components/propertyeditor/qlonglongvalidator.cpp
new file mode 100644
index 000000000..9396009b3
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/qlonglongvalidator.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/propertyeditor/qlonglongvalidator.h b/src/designer/src/components/propertyeditor/qlonglongvalidator.h
new file mode 100644
index 000000000..122351e4a
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/qlonglongvalidator.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/stringlisteditor.cpp b/src/designer/src/components/propertyeditor/stringlisteditor.cpp
new file mode 100644
index 000000000..cd55eff2e
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/stringlisteditor.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(QModelIndex,QModelIndex)),
+ this, SLOT(currentIndexChanged(QModelIndex,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/src/designer/src/components/propertyeditor/stringlisteditor.h b/src/designer/src/components/propertyeditor/stringlisteditor.h
new file mode 100644
index 000000000..8848d52d2
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/stringlisteditor.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/propertyeditor/stringlisteditor.ui b/src/designer/src/components/propertyeditor/stringlisteditor.ui
new file mode 100644
index 000000000..b206789b6
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/stringlisteditor.ui
@@ -0,0 +1,265 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/propertyeditor/stringlisteditorbutton.cpp b/src/designer/src/components/propertyeditor/stringlisteditorbutton.cpp
new file mode 100644
index 000000000..9e858cce1
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/stringlisteditorbutton.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/propertyeditor/stringlisteditorbutton.h b/src/designer/src/components/propertyeditor/stringlisteditorbutton.h
new file mode 100644
index 000000000..07bd291f5
--- /dev/null
+++ b/src/designer/src/components/propertyeditor/stringlisteditorbutton.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/connectdialog.cpp b/src/designer/src/components/signalsloteditor/connectdialog.cpp
new file mode 100644
index 000000000..64be11345
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/connectdialog.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = QVariant::fromValue(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 = QVariant::fromValue(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/src/designer/src/components/signalsloteditor/connectdialog.ui b/src/designer/src/components/signalsloteditor/connectdialog.ui
new file mode 100644
index 000000000..568516a42
--- /dev/null
+++ b/src/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" >
+ <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="1" >
+ <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" colspan="2" >
+ <widget class="QCheckBox" name="showAllCheckBox" >
+ <property name="text" >
+ <string>Show signals and slots inherited from QWidget</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" 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/src/designer/src/components/signalsloteditor/connectdialog_p.h b/src/designer/src/components/signalsloteditor/connectdialog_p.h
new file mode 100644
index 000000000..dd81483d5
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/connectdialog_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalslot_utils.cpp b/src/designer/src/components/signalsloteditor/signalslot_utils.cpp
new file mode 100644
index 000000000..ac1fe1cbf
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalslot_utils.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+
+ if (const qdesigner_internal::MetaDataBaseItem *mdbItem = metaDataBase->metaDataBaseItem(object)) {
+ 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 = 0;
+ if (obj_name == form->mainContainer()->objectName()) {
+ object = form->mainContainer();
+ } else {
+ object = form->mainContainer()->findChild<QObject*>(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 && 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 && 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/src/designer/src/components/signalsloteditor/signalslot_utils_p.h b/src/designer/src/components/signalsloteditor/signalslot_utils_p.h
new file mode 100644
index 000000000..0bc434c98
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalslot_utils_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditor.cpp b/src/designer/src/components/signalsloteditor/signalsloteditor.cpp
new file mode 100644
index 000000000..673864032
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor.cpp
@@ -0,0 +1,528 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = topLevel->findChild<QObject*>(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/src/designer/src/components/signalsloteditor/signalsloteditor.h b/src/designer/src/components/signalsloteditor/signalsloteditor.h
new file mode 100644
index 000000000..fca358760
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditor.pri b/src/designer/src/components/signalsloteditor/signalsloteditor.pri
new file mode 100644
index 000000000..e903ce114
--- /dev/null
+++ b/src/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/src/designer/src/components/signalsloteditor/signalsloteditor_global.h b/src/designer/src/components/signalsloteditor/signalsloteditor_global.h
new file mode 100644
index 000000000..122a32a92
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp b/src/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp
new file mode 100644
index 000000000..6c2aa3c11
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "signalsloteditor_plugin.h"
+
+QT_USE_NAMESPACE
+
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(SignalSlotEditorPlugin)
diff --git a/src/designer/src/components/signalsloteditor/signalsloteditor_p.h b/src/designer/src/components/signalsloteditor/signalsloteditor_p.h
new file mode 100644
index 000000000..bd01c2ef1
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp b/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp
new file mode 100644
index 000000000..7e1f67f08
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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::fromTheme("designer-edit-signals",
+ 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/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.h b/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.h
new file mode 100644
index 000000000..7ef5e2f5b
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_plugin.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp b/src/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp
new file mode 100644
index 000000000..a56acc37d
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/signalsloteditor/signalsloteditor_tool.h b/src/designer/src/components/signalsloteditor/signalsloteditor_tool.h
new file mode 100644
index 000000000..89b861ed3
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditor_tool.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/src/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp
new file mode 100644
index 000000000..b06a66f2c
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp
@@ -0,0 +1,864 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/QSortFilterProxyModel>
+#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>
+#include <QtGui/QToolBar>
+
+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 = mainContainer->findChildren<QAction*>();
+ 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 = mainContainer->findChildren<QButtonGroup *>();
+ 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 = QVariant::fromValue(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 = 0;
+ if (obj_name == m_form->mainContainer()->objectName()) {
+ object = m_form->mainContainer();
+ } else {
+ object = m_form->mainContainer()->findChild<QObject*>(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_proxy_model(new QSortFilterProxyModel(this)),
+ m_handling_selection_change(false)
+{
+ m_proxy_model->setSourceModel(m_model);
+ m_view->setModel(m_proxy_model);
+ m_view->setSortingEnabled(true);
+ 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->selectionModel(), SIGNAL(currentChanged(QModelIndex,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->setSpacing(0);
+
+ QToolBar *toolBar = new QToolBar;
+ toolBar->setIconSize(QSize(22, 22));
+ m_add_button->setIcon(createIconSet(QLatin1String("plus.png")));
+ connect(m_add_button, SIGNAL(clicked()), this, SLOT(addConnection()));
+ toolBar->addWidget(m_add_button);
+
+ m_remove_button->setIcon(createIconSet(QLatin1String("minus.png")));
+ connect(m_remove_button, SIGNAL(clicked()), this, SLOT(removeConnection()));
+ toolBar->addWidget(m_remove_button);
+
+ layout->addWidget(toolBar);
+ layout->addWidget(m_view);
+
+ 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 = form->findChild<SignalSlotEditor*>();
+ 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_proxy_model->mapFromSource(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(m_proxy_model->mapToSource(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/src/designer/src/components/signalsloteditor/signalsloteditorwindow.h b/src/designer/src/components/signalsloteditor/signalsloteditorwindow.h
new file mode 100644
index 000000000..179b6c5f4
--- /dev/null
+++ b/src/designer/src/components/signalsloteditor/signalsloteditorwindow.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITORWINDOW_H
+#define SIGNALSLOTEDITORWINDOW_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class QModelIndex;
+class QSortFilterProxyModel;
+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;
+ QSortFilterProxyModel *m_proxy_model;
+ bool m_handling_selection_change;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITORWINDOW_H
diff --git a/src/designer/src/components/tabordereditor/tabordereditor.cpp b/src/designer/src/components/tabordereditor/tabordereditor.cpp
new file mode 100644
index 000000000..e372bdc14
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 += qvariant_cast<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/src/designer/src/components/tabordereditor/tabordereditor.h b/src/designer/src/components/tabordereditor/tabordereditor.h
new file mode 100644
index 000000000..3eacd3739
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/tabordereditor/tabordereditor.pri b/src/designer/src/components/tabordereditor/tabordereditor.pri
new file mode 100644
index 000000000..786c6ae02
--- /dev/null
+++ b/src/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/src/designer/src/components/tabordereditor/tabordereditor_global.h b/src/designer/src/components/tabordereditor/tabordereditor_global.h
new file mode 100644
index 000000000..13b5e348d
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/tabordereditor/tabordereditor_instance.cpp b/src/designer/src/components/tabordereditor/tabordereditor_instance.cpp
new file mode 100644
index 000000000..6ff7903f7
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_instance.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "tabordereditor_plugin.h"
+
+QT_USE_NAMESPACE
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(TabOrderEditorPlugin)
diff --git a/src/designer/src/components/tabordereditor/tabordereditor_plugin.cpp b/src/designer/src/components/tabordereditor/tabordereditor_plugin.cpp
new file mode 100644
index 000000000..49581e5f6
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_plugin.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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"));
+ QIcon icon = QIcon::fromTheme("designer-edit-tabs",
+ QIcon(core->resourceLocation() + QLatin1String("/tabordertool.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*)));
+}
+
+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/src/designer/src/components/tabordereditor/tabordereditor_plugin.h b/src/designer/src/components/tabordereditor/tabordereditor_plugin.h
new file mode 100644
index 000000000..685804624
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_plugin.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/tabordereditor/tabordereditor_tool.cpp b/src/designer/src/components/tabordereditor/tabordereditor_tool.cpp
new file mode 100644
index 000000000..2914cb58a
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_tool.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/tabordereditor/tabordereditor_tool.h b/src/designer/src/components/tabordereditor/tabordereditor_tool.h
new file mode 100644
index 000000000..d978e4949
--- /dev/null
+++ b/src/designer/src/components/tabordereditor/tabordereditor_tool.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/button_taskmenu.cpp b/src/designer/src/components/taskmenu/button_taskmenu.cpp
new file mode 100644
index 000000000..953996b8c
--- /dev/null
+++ b/src/designer/src/components/taskmenu/button_taskmenu.cpp
@@ -0,0 +1,709 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(QVariant::fromValue(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 = 0;
+
+ 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/src/designer/src/components/taskmenu/button_taskmenu.h b/src/designer/src/components/taskmenu/button_taskmenu.h
new file mode 100644
index 000000000..e7350ca87
--- /dev/null
+++ b/src/designer/src/components/taskmenu/button_taskmenu.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/combobox_taskmenu.cpp b/src/designer/src/components/taskmenu/combobox_taskmenu.cpp
new file mode 100644
index 000000000..2b9b1fe19
--- /dev/null
+++ b/src/designer/src/components/taskmenu/combobox_taskmenu.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/combobox_taskmenu.h b/src/designer/src/components/taskmenu/combobox_taskmenu.h
new file mode 100644
index 000000000..c1eee4837
--- /dev/null
+++ b/src/designer/src/components/taskmenu/combobox_taskmenu.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/containerwidget_taskmenu.cpp b/src/designer/src/components/taskmenu/containerwidget_taskmenu.cpp
new file mode 100644
index 000000000..244ea00ff
--- /dev/null
+++ b/src/designer/src/components/taskmenu/containerwidget_taskmenu.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/containerwidget_taskmenu.h b/src/designer/src/components/taskmenu/containerwidget_taskmenu.h
new file mode 100644
index 000000000..6c5f1d481
--- /dev/null
+++ b/src/designer/src/components/taskmenu/containerwidget_taskmenu.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/groupbox_taskmenu.cpp b/src/designer/src/components/taskmenu/groupbox_taskmenu.cpp
new file mode 100644
index 000000000..1fae0f8ba
--- /dev/null
+++ b/src/designer/src/components/taskmenu/groupbox_taskmenu.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/groupbox_taskmenu.h b/src/designer/src/components/taskmenu/groupbox_taskmenu.h
new file mode 100644
index 000000000..d30d8b1b6
--- /dev/null
+++ b/src/designer/src/components/taskmenu/groupbox_taskmenu.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/inplace_editor.cpp b/src/designer/src/components/taskmenu/inplace_editor.cpp
new file mode 100644
index 000000000..fd74b25f4
--- /dev/null
+++ b/src/designer/src/components/taskmenu/inplace_editor.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = qvariant_cast<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, QVariant::fromValue(m_value));
+ } else {
+ m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, QVariant::fromValue(m_value));
+ }
+}
+
+void TaskMenuInlineEditor::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/taskmenu/inplace_editor.h b/src/designer/src/components/taskmenu/inplace_editor.h
new file mode 100644
index 000000000..573185cb8
--- /dev/null
+++ b/src/designer/src/components/taskmenu/inplace_editor.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/inplace_widget_helper.cpp b/src/designer/src/components/taskmenu/inplace_widget_helper.cpp
new file mode 100644
index 000000000..47554b3a8
--- /dev/null
+++ b/src/designer/src/components/taskmenu/inplace_widget_helper.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/inplace_widget_helper.h b/src/designer/src/components/taskmenu/inplace_widget_helper.h
new file mode 100644
index 000000000..663516004
--- /dev/null
+++ b/src/designer/src/components/taskmenu/inplace_widget_helper.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/itemlisteditor.cpp b/src/designer/src/components/taskmenu/itemlisteditor.cpp
new file mode 100644
index 000000000..a04246de5
--- /dev/null
+++ b/src/designer/src/components/taskmenu/itemlisteditor.cpp
@@ -0,0 +1,478 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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)
+ : QWidget(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);
+}
+
+static const char * const itemFlagNames[] = {
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Selectable"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Editable"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "DragEnabled"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "DropEnabled"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "UserCheckable"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Enabled"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Tristate"),
+ 0
+};
+
+static const char * const checkStateNames[] = {
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Unchecked"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "PartiallyChecked"),
+ QT_TRANSLATE_NOOP("AbstractItemEditor", "Checked"),
+ 0
+};
+
+static QStringList c2qStringList(const char * const in[])
+{
+ QStringList out;
+ for (int i = 0; in[i]; i++)
+ out << AbstractItemEditor::tr(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 && !qvariant_cast<PropertySheetIconValue>(prop->value()).mask())
+ || (role == Qt::FontRole && !qvariant_cast<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, QVariant::fromValue(iconCache()->icon(qvariant_cast<PropertySheetIconValue>(prop->value()))));
+ break;
+ case Qt::DisplayPropertyRole:
+ setItemData(Qt::EditRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::ToolTipPropertyRole:
+ setItemData(Qt::ToolTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::StatusTipPropertyRole:
+ setItemData(Qt::StatusTipRole, QVariant::fromValue(qvariant_cast<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::WhatsThisPropertyRole:
+ setItemData(Qt::WhatsThisRole, QVariant::fromValue(qvariant_cast<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(QVariant::fromValue((int)QListWidgetItem().flags()));
+ else
+ prop->setValue(QVariant(prop->valueType(), (void *)0));
+ prop->setModified(false);
+
+ setItemData(role, QVariant());
+ if (role == Qt::DecorationPropertyRole)
+ setItemData(Qt::DecorationRole, QVariant::fromValue(QIcon()));
+ if (role == Qt::DisplayPropertyRole)
+ setItemData(Qt::EditRole, QVariant::fromValue(QString()));
+ if (role == Qt::ToolTipPropertyRole)
+ setItemData(Qt::ToolTipRole, QVariant::fromValue(QString()));
+ if (role == Qt::StatusTipPropertyRole)
+ setItemData(Qt::StatusTipRole, QVariant::fromValue(QString()));
+ if (role == Qt::WhatsThisPropertyRole)
+ setItemData(Qt::WhatsThisRole, QVariant::fromValue(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 = QVariant::fromValue((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()));
+ setPropertyBrowserVisible(false);
+
+ 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, QVariant::fromValue(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 = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole));
+ val.setValue(item->text());
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(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,
+ QVariant::fromValue(val));
+ updateBrowser();
+}
+
+void ItemListEditor::togglePropertyBrowser()
+{
+ setPropertyBrowserVisible(!m_propertyBrowser->isVisible());
+}
+
+void ItemListEditor::setPropertyBrowserVisible(bool v)
+{
+ ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<"));
+ m_propertyBrowser->setVisible(v);
+}
+
+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 = qvariant_cast<QFont>(newValue).resolve(oldFont);
+ newValue = QVariant::fromValue(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();
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/taskmenu/itemlisteditor.h b/src/designer/src/components/taskmenu/itemlisteditor.h
new file mode 100644
index 000000000..ffacad293
--- /dev/null
+++ b/src/designer/src/components/taskmenu/itemlisteditor.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+class QVBoxLayout;
+
+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 QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit 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 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:
+ explicit 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;
+
+private:
+ void setPropertyBrowserVisible(bool v);
+ void updateEditor();
+ Ui::ItemListEditor ui;
+ bool m_updating;
+ QString m_newItemText;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ITEMLISTEDITOR_H
diff --git a/src/designer/src/components/taskmenu/itemlisteditor.ui b/src/designer/src/components/taskmenu/itemlisteditor.ui
new file mode 100644
index 000000000..a13703f90
--- /dev/null
+++ b/src/designer/src/components/taskmenu/itemlisteditor.ui
@@ -0,0 +1,156 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/taskmenu/label_taskmenu.cpp b/src/designer/src/components/taskmenu/label_taskmenu.cpp
new file mode 100644
index 000000000..5f0acb209
--- /dev/null
+++ b/src/designer/src/components/taskmenu/label_taskmenu.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/label_taskmenu.h b/src/designer/src/components/taskmenu/label_taskmenu.h
new file mode 100644
index 000000000..7f3549128
--- /dev/null
+++ b/src/designer/src/components/taskmenu/label_taskmenu.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/layouttaskmenu.cpp b/src/designer/src/components/taskmenu/layouttaskmenu.cpp
new file mode 100644
index 000000000..10d5d7c54
--- /dev/null
+++ b/src/designer/src/components/taskmenu/layouttaskmenu.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/layouttaskmenu.h b/src/designer/src/components/taskmenu/layouttaskmenu.h
new file mode 100644
index 000000000..ca52596ee
--- /dev/null
+++ b/src/designer/src/components/taskmenu/layouttaskmenu.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/lineedit_taskmenu.cpp b/src/designer/src/components/taskmenu/lineedit_taskmenu.cpp
new file mode 100644
index 000000000..c00c493b1
--- /dev/null
+++ b/src/designer/src/components/taskmenu/lineedit_taskmenu.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "lineedit_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/src/designer/src/components/taskmenu/lineedit_taskmenu.h b/src/designer/src/components/taskmenu/lineedit_taskmenu.h
new file mode 100644
index 000000000..239590bb8
--- /dev/null
+++ b/src/designer/src/components/taskmenu/lineedit_taskmenu.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LINEEDIT_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/src/designer/src/components/taskmenu/listwidget_taskmenu.cpp b/src/designer/src/components/taskmenu/listwidget_taskmenu.cpp
new file mode 100644
index 000000000..bd8f6b9f8
--- /dev/null
+++ b/src/designer/src/components/taskmenu/listwidget_taskmenu.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/listwidget_taskmenu.h b/src/designer/src/components/taskmenu/listwidget_taskmenu.h
new file mode 100644
index 000000000..e7e527a38
--- /dev/null
+++ b/src/designer/src/components/taskmenu/listwidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/listwidgeteditor.cpp b/src/designer/src/components/taskmenu/listwidgeteditor.cpp
new file mode 100644
index 000000000..7c81ea47e
--- /dev/null
+++ b/src/designer/src/components/taskmenu/listwidgeteditor.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/listwidgeteditor.h b/src/designer/src/components/taskmenu/listwidgeteditor.h
new file mode 100644
index 000000000..12d0591f2
--- /dev/null
+++ b/src/designer/src/components/taskmenu/listwidgeteditor.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LISTWIDGETEDITOR_H
+#define LISTWIDGETEDITOR_H
+
+#include "itemlisteditor.h"
+#include <qdesigner_command_p.h>
+
+#include <QtGui/QWidget>
+
+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/src/designer/src/components/taskmenu/menutaskmenu.cpp b/src/designer/src/components/taskmenu/menutaskmenu.cpp
new file mode 100644
index 000000000..cbcecb122
--- /dev/null
+++ b/src/designer/src/components/taskmenu/menutaskmenu.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/menutaskmenu.h b/src/designer/src/components/taskmenu/menutaskmenu.h
new file mode 100644
index 000000000..35cb061b4
--- /dev/null
+++ b/src/designer/src/components/taskmenu/menutaskmenu.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/tablewidget_taskmenu.cpp b/src/designer/src/components/taskmenu/tablewidget_taskmenu.cpp
new file mode 100644
index 000000000..e98714f62
--- /dev/null
+++ b/src/designer/src/components/taskmenu/tablewidget_taskmenu.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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);
+
+ TableWidgetEditorDialog 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/src/designer/src/components/taskmenu/tablewidget_taskmenu.h b/src/designer/src/components/taskmenu/tablewidget_taskmenu.h
new file mode 100644
index 000000000..cbf71fea6
--- /dev/null
+++ b/src/designer/src/components/taskmenu/tablewidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/tablewidgeteditor.cpp b/src/designer/src/components/taskmenu/tablewidgeteditor.cpp
new file mode 100644
index 000000000..35f1a0e49
--- /dev/null
+++ b/src/designer/src/components/taskmenu/tablewidgeteditor.cpp
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+
+namespace qdesigner_internal {
+
+TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog)
+ : AbstractItemEditor(form, 0), 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(dialog);
+
+ injectPropertyBrowser(ui.itemsTab, ui.widget);
+ connect(ui.showPropertiesButton, SIGNAL(clicked()),
+ this, SLOT(togglePropertyBrowser()));
+ setPropertyBrowserVisible(false);
+
+ 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()));
+
+ connect(ui.tableWidget, SIGNAL(currentCellChanged(int,int,int,int)),
+ this, SLOT(on_tableWidget_currentCellChanged(int,int,int,int)));
+ connect(ui.tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)),
+ this, SLOT(on_tableWidget_itemChanged(QTableWidgetItem*)));
+ connect(m_columnEditor, SIGNAL(indexChanged(int)),
+ this, SLOT(on_columnEditor_indexChanged(int)));
+ connect(m_columnEditor, SIGNAL(itemChanged(int,int,QVariant)),
+ this, SLOT(on_columnEditor_itemChanged(int,int,QVariant)));
+ connect(m_columnEditor, SIGNAL(itemInserted(int)),
+ this, SLOT(on_columnEditor_itemInserted(int)));
+ connect(m_columnEditor, SIGNAL(itemDeleted(int)),
+ this, SLOT(on_columnEditor_itemDeleted(int)));
+ connect(m_columnEditor, SIGNAL(itemMovedUp(int)),
+ this, SLOT(on_columnEditor_itemMovedUp(int)));
+ connect(m_columnEditor, SIGNAL(itemMovedDown(int)),
+ this, SLOT(on_columnEditor_itemMovedDown(int)));
+
+ connect(m_rowEditor, SIGNAL(indexChanged(int)),
+ this, SLOT(on_rowEditor_indexChanged(int)));
+ connect(m_rowEditor, SIGNAL(itemChanged(int,int,QVariant)),
+ this, SLOT(on_rowEditor_itemChanged(int,int,QVariant)));
+ connect(m_rowEditor, SIGNAL(itemInserted(int)),
+ this, SLOT(on_rowEditor_itemInserted(int)));
+ connect(m_rowEditor, SIGNAL(itemDeleted(int)),
+ this, SLOT(on_rowEditor_itemDeleted(int)));
+ connect(m_rowEditor, SIGNAL(itemMovedUp(int)),
+ this, SLOT(on_rowEditor_itemMovedUp(int)));
+ connect(m_rowEditor, SIGNAL(itemMovedDown(int)),
+ this, SLOT(on_rowEditor_itemMovedDown(int)));
+}
+
+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 = qvariant_cast<QFont>(newValue).resolve(oldFont);
+ newValue = QVariant::fromValue(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 = qvariant_cast<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole));
+ val.setValue(item->text());
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(Qt::DisplayPropertyRole, QVariant::fromValue(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::setPropertyBrowserVisible(bool v)
+{
+ ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<"));
+ m_propertyBrowser->setVisible(v);
+}
+
+void TableWidgetEditor::togglePropertyBrowser()
+{
+ setPropertyBrowserVisible(!m_propertyBrowser->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, QVariant::fromValue(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, QVariant::fromValue(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);
+}
+
+TableWidgetEditorDialog::TableWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) :
+ QDialog(parent), m_editor(form, this)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+}
+
+TableWidgetContents TableWidgetEditorDialog::fillContentsFromTableWidget(QTableWidget *tableWidget)
+{
+ return m_editor.fillContentsFromTableWidget(tableWidget);
+}
+
+TableWidgetContents TableWidgetEditorDialog::contents() const
+{
+ return m_editor.contents();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/taskmenu/tablewidgeteditor.h b/src/designer/src/components/taskmenu/tablewidgeteditor.h
new file mode 100644
index 000000000..1d5ad1f57
--- /dev/null
+++ b/src/designer/src/components/taskmenu/tablewidgeteditor.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABLEWIDGETEDITOR_H
+#define TABLEWIDGETEDITOR_H
+
+#include "ui_tablewidgeteditor.h"
+
+#include "listwidgeteditor.h"
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QTableWidget;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class FormWindowBase;
+class PropertySheetIconValue;
+
+class TableWidgetEditor: public AbstractItemEditor
+{
+ Q_OBJECT
+public:
+ explicit TableWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog);
+
+ 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 setPropertyBrowserVisible(bool v);
+ 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;
+};
+
+class TableWidgetEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit TableWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ TableWidgetContents fillContentsFromTableWidget(QTableWidget *tableWidget);
+ TableWidgetContents contents() const;
+
+private:
+ TableWidgetEditor m_editor;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TABLEWIDGETEDITOR_H
diff --git a/src/designer/src/components/taskmenu/tablewidgeteditor.ui b/src/designer/src/components/taskmenu/tablewidgeteditor.ui
new file mode 100644
index 000000000..33691e94d
--- /dev/null
+++ b/src/designer/src/components/taskmenu/tablewidgeteditor.ui
@@ -0,0 +1,157 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/taskmenu/taskmenu.pri b/src/designer/src/components/taskmenu/taskmenu.pri
new file mode 100644
index 000000000..066b92980
--- /dev/null
+++ b/src/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/src/designer/src/components/taskmenu/taskmenu_component.cpp b/src/designer/src/components/taskmenu/taskmenu_component.cpp
new file mode 100644
index 000000000..c7f395349
--- /dev/null
+++ b/src/designer/src/components/taskmenu/taskmenu_component.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/taskmenu_component.h b/src/designer/src/components/taskmenu/taskmenu_component.h
new file mode 100644
index 000000000..762567c84
--- /dev/null
+++ b/src/designer/src/components/taskmenu/taskmenu_component.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/taskmenu_global.h b/src/designer/src/components/taskmenu/taskmenu_global.h
new file mode 100644
index 000000000..df276016c
--- /dev/null
+++ b/src/designer/src/components/taskmenu/taskmenu_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/textedit_taskmenu.cpp b/src/designer/src/components/taskmenu/textedit_taskmenu.cpp
new file mode 100644
index 000000000..510a32f5f
--- /dev/null
+++ b/src/designer/src/components/taskmenu/textedit_taskmenu.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/textedit_taskmenu.h b/src/designer/src/components/taskmenu/textedit_taskmenu.h
new file mode 100644
index 000000000..1429f315e
--- /dev/null
+++ b/src/designer/src/components/taskmenu/textedit_taskmenu.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/toolbar_taskmenu.cpp b/src/designer/src/components/taskmenu/toolbar_taskmenu.cpp
new file mode 100644
index 000000000..8db233ca2
--- /dev/null
+++ b/src/designer/src/components/taskmenu/toolbar_taskmenu.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/components/taskmenu/toolbar_taskmenu.h b/src/designer/src/components/taskmenu/toolbar_taskmenu.h
new file mode 100644
index 000000000..6818e2607
--- /dev/null
+++ b/src/designer/src/components/taskmenu/toolbar_taskmenu.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/treewidget_taskmenu.cpp b/src/designer/src/components/taskmenu/treewidget_taskmenu.cpp
new file mode 100644
index 000000000..96210dcdb
--- /dev/null
+++ b/src/designer/src/components/taskmenu/treewidget_taskmenu.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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);
+
+ TreeWidgetEditorDialog 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/src/designer/src/components/taskmenu/treewidget_taskmenu.h b/src/designer/src/components/taskmenu/treewidget_taskmenu.h
new file mode 100644
index 000000000..e5a9e9073
--- /dev/null
+++ b/src/designer/src/components/taskmenu/treewidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/taskmenu/treewidgeteditor.cpp b/src/designer/src/components/taskmenu/treewidgeteditor.cpp
new file mode 100644
index 000000000..f5f6035f2
--- /dev/null
+++ b/src/designer/src/components/taskmenu/treewidgeteditor.cpp
@@ -0,0 +1,642 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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, QDialog *dialog)
+ : AbstractItemEditor(form, 0), m_updatingBrowser(false)
+{
+ m_columnEditor = new ItemListEditor(form, this);
+ m_columnEditor->setObjectName(QLatin1String("columnEditor"));
+ m_columnEditor->setNewItemText(tr("New Column"));
+ ui.setupUi(dialog);
+
+ injectPropertyBrowser(ui.itemsTab, ui.widget);
+ connect(ui.showPropertiesButton, SIGNAL(clicked()),
+ this, SLOT(togglePropertyBrowser()));
+ setPropertyBrowserVisible(false);
+
+ 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(ui.newItemButton, SIGNAL(clicked()), this, SLOT(on_newItemButton_clicked()));
+ connect(ui.newSubItemButton, SIGNAL(clicked()), this, SLOT(on_newSubItemButton_clicked()));
+ connect(ui.moveItemUpButton, SIGNAL(clicked()), this, SLOT(on_moveItemUpButton_clicked()));
+ connect(ui.moveItemDownButton, SIGNAL(clicked()), this, SLOT(on_moveItemDownButton_clicked()));
+ connect(ui.moveItemRightButton, SIGNAL(clicked()), this, SLOT(on_moveItemRightButton_clicked()));
+ connect(ui.moveItemLeftButton, SIGNAL(clicked()), this, SLOT(on_moveItemLeftButton_clicked()));
+ connect(ui.treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
+ this, SLOT(on_treeWidget_currentItemChanged()));
+ connect(ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
+ this, SLOT(on_treeWidget_itemChanged(QTreeWidgetItem*,int)));
+
+ connect(m_columnEditor, SIGNAL(indexChanged(int)),
+ this, SLOT(on_columnEditor_indexChanged(int)));
+ connect(m_columnEditor, SIGNAL(itemChanged(int,int,QVariant)),
+ this, SLOT(on_columnEditor_itemChanged(int,int,QVariant)));
+ connect(m_columnEditor, SIGNAL(itemInserted(int)),
+ this, SLOT(on_columnEditor_itemInserted(int)));
+ connect(m_columnEditor, SIGNAL(itemDeleted(int)),
+ this, SLOT(on_columnEditor_itemDeleted(int)));
+ connect(m_columnEditor, SIGNAL(itemMovedUp(int)),
+ this, SLOT(on_columnEditor_itemMovedUp(int)));
+ connect(m_columnEditor, SIGNAL(itemMovedDown(int)),
+ this, SLOT(on_columnEditor_itemMovedDown(int)));
+
+ 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 = qvariant_cast<QFont>(newValue).resolve(oldFont);
+ newValue = QVariant::fromValue(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, QVariant::fromValue(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, QVariant::fromValue(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()
+{
+ setPropertyBrowserVisible(!m_propertyBrowser->isVisible());
+}
+
+void TreeWidgetEditor::setPropertyBrowserVisible(bool v)
+{
+ ui.showPropertiesButton->setText(v ? tr("Properties &>>") : tr("Properties &<<"));
+ m_propertyBrowser->setVisible(v);
+}
+
+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 = qvariant_cast<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole));
+ val.setValue(item->text(column));
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(column, Qt::DisplayPropertyRole, QVariant::fromValue(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, qvariant_cast<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);
+}
+
+TreeWidgetEditorDialog::TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent) :
+ QDialog(parent), m_editor(form, this)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+}
+
+TreeWidgetContents TreeWidgetEditorDialog::fillContentsFromTreeWidget(QTreeWidget *treeWidget)
+{
+ return m_editor.fillContentsFromTreeWidget(treeWidget);
+}
+
+TreeWidgetContents TreeWidgetEditorDialog::contents() const
+{
+ return m_editor.contents();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/components/taskmenu/treewidgeteditor.h b/src/designer/src/components/taskmenu/treewidgeteditor.h
new file mode 100644
index 000000000..f502bf3e4
--- /dev/null
+++ b/src/designer/src/components/taskmenu/treewidgeteditor.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TREEWIDGETEDITOR_H
+#define TREEWIDGETEDITOR_H
+
+#include "ui_treewidgeteditor.h"
+
+#include "listwidgeteditor.h"
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class FormWindowBase;
+class PropertySheetIconValue;
+
+class TreeWidgetEditor: public AbstractItemEditor
+{
+ Q_OBJECT
+public:
+ explicit TreeWidgetEditor(QDesignerFormWindowInterface *form, QDialog *dialog);
+
+ 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:
+ void setPropertyBrowserVisible(bool v);
+ 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;
+};
+
+class TreeWidgetEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit TreeWidgetEditorDialog(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ TreeWidgetContents fillContentsFromTreeWidget(QTreeWidget *treeWidget);
+ TreeWidgetContents contents() const;
+
+private:
+ TreeWidgetEditor m_editor;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TREEWIDGETEDITOR_H
diff --git a/src/designer/src/components/taskmenu/treewidgeteditor.ui b/src/designer/src/components/taskmenu/treewidgeteditor.ui
new file mode 100644
index 000000000..7a71d4404
--- /dev/null
+++ b/src/designer/src/components/taskmenu/treewidgeteditor.ui
@@ -0,0 +1,257 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/widgetbox/widgetbox.cpp b/src/designer/src/components/widgetbox/widgetbox.cpp
new file mode 100644
index 000000000..c9b0d040a
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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)));
+
+ QToolBar *toolBar = new QToolBar(this);
+ toolBar->addWidget(filterWidget);
+ l->addWidget(toolBar);
+
+ // 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/src/designer/src/components/widgetbox/widgetbox.h b/src/designer/src/components/widgetbox/widgetbox.h
new file mode 100644
index 000000000..a19c756aa
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/widgetbox/widgetbox.pri b/src/designer/src/components/widgetbox/widgetbox.pri
new file mode 100644
index 000000000..dd8ad002e
--- /dev/null
+++ b/src/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/src/designer/src/components/widgetbox/widgetbox.qrc b/src/designer/src/components/widgetbox/widgetbox.qrc
new file mode 100644
index 000000000..7ecf78c85
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/widgetbox">
+ <file>widgetbox.xml</file>
+ </qresource>
+</RCC>
diff --git a/src/designer/src/components/widgetbox/widgetbox.xml b/src/designer/src/components/widgetbox/widgetbox.xml
new file mode 100644
index 000000000..4286e0d6c
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox.xml
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/components/widgetbox/widgetbox_dnditem.cpp b/src/designer/src/components/widgetbox/widgetbox_dnditem.cpp
new file mode 100644
index 000000000..c122c8411
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox_dnditem.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <qsimpleresource_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);
+ virtual void createCustomWidgets(DomCustomWidgets *);
+};
+
+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;
+}
+
+void WidgetBoxResource::createCustomWidgets(DomCustomWidgets *dc)
+{
+ // Make a promotion entry in case someone has a promoted widget
+ // in the scratchpad.
+ QSimpleResource::handleDomCustomWidgets(core(), dc);
+
+}
+
+/*******************************************************************************
+** 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 = fakeTopLevel->findChildren<QWidget*>().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/src/designer/src/components/widgetbox/widgetbox_dnditem.h b/src/designer/src/components/widgetbox/widgetbox_dnditem.h
new file mode 100644
index 000000000..010cedc03
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox_dnditem.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/widgetbox/widgetbox_global.h b/src/designer/src/components/widgetbox/widgetbox_global.h
new file mode 100644
index 000000000..0d550c748
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetbox_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/widgetbox/widgetboxcategorylistview.cpp b/src/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
new file mode 100644
index 000000000..d2a0d43c0
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 QString &filter,
+ const QIcon &icon,
+ bool editable);
+
+ QDesignerWidgetBoxInterface::Widget widget;
+ QString toolTip;
+ QString whatsThis;
+ QString filter;
+ QIcon icon;
+ bool editable;
+};
+
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry() :
+ editable(false)
+{
+}
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &w,
+ const QString &filterIn,
+ const QIcon &i, bool e) :
+ widget(w),
+ filter(filterIn),
+ 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;
+
+ QRegExp m_classNameRegExp;
+ QDesignerFormEditorInterface *m_core;
+ WidgetBoxCategoryEntrys m_items;
+ QListView::ViewMode m_viewMode;
+};
+
+WidgetBoxCategoryModel::WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent) :
+ QAbstractListModel(parent),
+ m_classNameRegExp(QLatin1String("<widget +class *= *\"([^\"]+)\"")),
+ m_core(core),
+ m_viewMode(QListView::ListMode)
+{
+ Q_ASSERT(m_classNameRegExp.isValid());
+}
+
+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. Filter on name + class name if it is different and not a layout.
+ QString filter = widget.name();
+ if (!filter.contains(QLatin1String("Layout")) && m_classNameRegExp.indexIn(widget.domXml()) != -1) {
+ const QString className = m_classNameRegExp.cap(1);
+ if (!filter.contains(className))
+ filter += className;
+ }
+ WidgetBoxCategoryEntry item(widget, filter, 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.filter;
+ }
+ 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/src/designer/src/components/widgetbox/widgetboxcategorylistview.h b/src/designer/src/components/widgetbox/widgetboxcategorylistview.h
new file mode 100644
index 000000000..5e6df1149
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetboxcategorylistview.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/components/widgetbox/widgetboxtreewidget.cpp b/src/designer/src/components/widgetbox/widgetboxtreewidget.cpp
new file mode 100644
index 000000000..f4b567b69
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetboxtreewidget.cpp
@@ -0,0 +1,1001 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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);
+ if (embedItem == 0)
+ return;
+
+ 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/src/designer/src/components/widgetbox/widgetboxtreewidget.h b/src/designer/src/components/widgetbox/widgetboxtreewidget.h
new file mode 100644
index 000000000..db4f7cdb1
--- /dev/null
+++ b/src/designer/src/components/widgetbox/widgetboxtreewidget.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/Info_mac.plist b/src/designer/src/designer/Info_mac.plist
new file mode 100644
index 000000000..f19176fa7
--- /dev/null
+++ b/src/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>uifile.icns</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/src/designer/src/designer/appfontdialog.cpp b/src/designer/src/designer/appfontdialog.cpp
new file mode 100644
index 000000000..00b91fa0d
--- /dev/null
+++ b/src/designer/src/designer/appfontdialog.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/appfontdialog.h b/src/designer/src/designer/appfontdialog.h
new file mode 100644
index 000000000..a373217ac
--- /dev/null
+++ b/src/designer/src/designer/appfontdialog.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/assistantclient.cpp b/src/designer/src/designer/assistantclient.cpp
new file mode 100644
index 000000000..0433c5c51
--- /dev/null
+++ b/src/designer/src/designer/assistantclient.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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('\n') << 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/src/designer/src/designer/assistantclient.h b/src/designer/src/designer/assistantclient.h
new file mode 100644
index 000000000..67257d191
--- /dev/null
+++ b/src/designer/src/designer/assistantclient.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/designer.icns b/src/designer/src/designer/designer.icns
new file mode 100644
index 000000000..9940214fc
--- /dev/null
+++ b/src/designer/src/designer/designer.icns
Binary files differ
diff --git a/src/designer/src/designer/designer.ico b/src/designer/src/designer/designer.ico
new file mode 100644
index 000000000..ef667333d
--- /dev/null
+++ b/src/designer/src/designer/designer.ico
Binary files differ
diff --git a/src/designer/src/designer/designer.pro b/src/designer/src/designer/designer.pro
new file mode 100644
index 000000000..8564e96cb
--- /dev/null
+++ b/src/designer/src/designer/designer.pro
@@ -0,0 +1,90 @@
+
+DESTDIR = ../../../../bin
+QT += xml network
+contains(QT_CONFIG, script): QT += script
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+INCLUDEPATH += \
+ ../lib/sdk \
+ ../lib/extension \
+ ../lib/shared \
+ ../lib/uilib \
+ extra
+
+QMAKE_LIBDIR += ../../lib ../../../../lib
+LIBS += -lQtDesignerComponents -lQtDesigner
+
+RESOURCES += designer.qrc
+
+contains(CONFIG, static) {
+ DEFINES += QT_DESIGNER_STATIC
+}
+
+TARGET = designer
+
+include(../../../shared/fontpanel/fontpanel.pri)
+include(../../../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
+ FILETYPES.files = uifile.icns
+ FILETYPES.path = Contents/Resources
+ QMAKE_BUNDLE_DATA += FILETYPES
+}
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+include(../sharedcomponents.pri)
+
+unix:!mac:LIBS += -lm
diff --git a/src/designer/src/designer/designer.qrc b/src/designer/src/designer/designer.qrc
new file mode 100644
index 000000000..fac8120d0
--- /dev/null
+++ b/src/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/src/designer/src/designer/designer.rc b/src/designer/src/designer/designer.rc
new file mode 100644
index 000000000..9c396b555
--- /dev/null
+++ b/src/designer/src/designer/designer.rc
@@ -0,0 +1,32 @@
+#include "winver.h"
+
+IDI_ICON1 ICON DISCARDABLE "designer.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGS 0x0L
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)"
+ VALUE "FileDescription", "Qt Designer"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
+ VALUE "InternalName", "designer"
+ VALUE "OriginalFilename", "designer.exe"
+ VALUE "ProductName", "Qt Designer"
+ VALUE "ProductVersion", "1.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/src/designer/src/designer/designer_enums.h b/src/designer/src/designer/designer_enums.h
new file mode 100644
index 000000000..ca115c37a
--- /dev/null
+++ b/src/designer/src/designer/designer_enums.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERENUMS_H
+#define DESIGNERENUMS_H
+
+enum UIMode
+{
+ NeutralMode,
+ TopLevelMode,
+ DockedMode
+};
+
+#endif // DESIGNERENUMS_H
diff --git a/src/designer/src/designer/images/designer.png b/src/designer/src/designer/images/designer.png
new file mode 100644
index 000000000..0988fcee3
--- /dev/null
+++ b/src/designer/src/designer/images/designer.png
Binary files differ
diff --git a/src/designer/src/designer/images/mdi.png b/src/designer/src/designer/images/mdi.png
new file mode 100644
index 000000000..5012ab304
--- /dev/null
+++ b/src/designer/src/designer/images/mdi.png
Binary files differ
diff --git a/src/designer/src/designer/images/sdi.png b/src/designer/src/designer/images/sdi.png
new file mode 100644
index 000000000..7fff6e8b6
--- /dev/null
+++ b/src/designer/src/designer/images/sdi.png
Binary files differ
diff --git a/src/designer/src/designer/images/workbench.png b/src/designer/src/designer/images/workbench.png
new file mode 100644
index 000000000..06716a44f
--- /dev/null
+++ b/src/designer/src/designer/images/workbench.png
Binary files differ
diff --git a/src/designer/src/designer/main.cpp b/src/designer/src/designer/main.cpp
new file mode 100644
index 000000000..8a5b5c044
--- /dev/null
+++ b/src/designer/src/designer/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDir>
+
+#include <stdlib.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ Q_INIT_RESOURCE(designer);
+
+ QDesigner app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
+
+ return app.exec();
+}
diff --git a/src/designer/src/designer/mainwindow.cpp b/src/designer/src/designer/mainwindow.cpp
new file mode 100644
index 000000000..67e1a4053
--- /dev/null
+++ b/src/designer/src/designer/mainwindow.cpp
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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->property(QDesignerActions::defaultToolbarPropertyName).toBool())
+ 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)
+{
+ // Note that whenever you want to add a new tool bar here, you also have to update the default
+ // action groups added to the toolbar manager in the mainwindow constructor
+ 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);
+ }
+
+ QString category(tr("File"));
+ foreach(QAction *action, actions->fileActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Edit");
+ foreach(QAction *action, actions->editActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Tools");
+ foreach(QAction *action, actions->toolActions()->actions())
+ m_manager->addAction(action, category);
+
+ category = tr("Form");
+ foreach(QAction *action, actions->formActions()->actions())
+ m_manager->addAction(action, category);
+
+ 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/src/designer/src/designer/mainwindow.h b/src/designer/src/designer/mainwindow.h
new file mode 100644
index 000000000..e39e57203
--- /dev/null
+++ b/src/designer/src/designer/mainwindow.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/newform.cpp b/src/designer/src/designer/newform.cpp
new file mode 100644
index 000000000..34461f52a
--- /dev/null
+++ b/src/designer/src/designer/newform.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/newform.h b/src/designer/src/designer/newform.h
new file mode 100644
index 000000000..ad51118b9
--- /dev/null
+++ b/src/designer/src/designer/newform.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/preferencesdialog.cpp b/src/designer/src/designer/preferencesdialog.cpp
new file mode 100644
index 000000000..a27e366a5
--- /dev/null
+++ b/src/designer/src/designer/preferencesdialog.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/preferencesdialog.h b/src/designer/src/designer/preferencesdialog.h
new file mode 100644
index 000000000..5ffd7d365
--- /dev/null
+++ b/src/designer/src/designer/preferencesdialog.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/preferencesdialog.ui b/src/designer/src/designer/preferencesdialog.ui
new file mode 100644
index 000000000..28d14bb83
--- /dev/null
+++ b/src/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/src/designer/src/designer/qdesigner.cpp b/src/designer/src/designer/qdesigner.cpp
new file mode 100644
index 000000000..1e838c197
--- /dev/null
+++ b/src/designer/src/designer/qdesigner.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/designer/qdesigner.h b/src/designer/src/designer/qdesigner.h
new file mode 100644
index 000000000..ff45edffd
--- /dev/null
+++ b/src/designer/src/designer/qdesigner.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/qdesigner_actions.cpp b/src/designer/src/designer/qdesigner_actions.cpp
new file mode 100644
index 000000000..a84e0732d
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_actions.cpp
@@ -0,0 +1,1437 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+
+const char *QDesignerActions::defaultToolbarPropertyName = "__qt_defaultToolBarAction";
+
+//#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)
+{
+#ifdef Q_WS_X11
+ m_newFormAction->setIcon(QIcon::fromTheme("document-new", m_newFormAction->icon()));
+ m_openFormAction->setIcon(QIcon::fromTheme("document-open", m_openFormAction->icon()));
+ m_saveFormAction->setIcon(QIcon::fromTheme("document-save", m_saveFormAction->icon()));
+ m_saveFormAsAction->setIcon(QIcon::fromTheme("document-save-as", m_saveFormAsAction->icon()));
+ m_printPreviewAction->setIcon(QIcon::fromTheme("document-print", m_printPreviewAction->icon()));
+ m_closeFormAction->setIcon(QIcon::fromTheme("window-close", m_closeFormAction->icon()));
+ m_quitAction->setIcon(QIcon::fromTheme("application-exit", m_quitAction->icon()));
+#endif
+
+ 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();
+
+ m_newFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ m_openFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ m_saveFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+ 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->setShortcuts(QKeySequence::Quit);
+ 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());
+
+ formWindowManager->actionLower()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionRaise()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+//
+// 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);
+ QIcon fallback(m_core->resourceLocation() + QLatin1String("/widgettool.png"));
+ m_editWidgetsAction->setIcon(QIcon::fromTheme("designer-edit-widget", fallback));
+ connect(m_editWidgetsAction, SIGNAL(triggered()), this, SLOT(editWidgetsSlot()));
+ m_editWidgetsAction->setChecked(true);
+ m_editWidgetsAction->setEnabled(false);
+ m_editWidgetsAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ 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->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ 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));
+
+ formWindowManager->actionHorizontalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionVerticalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionSplitHorizontal()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionSplitVertical()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionGridLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionFormLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionBreakLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+ formWindowManager->actionAdjustSize()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+ 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(QIcon::fromTheme("edit-clear"), 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(QIcon::fromTheme("document-open-recent"), 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 (const 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.clear();
+ 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/src/designer/src/designer/qdesigner_actions.h b/src/designer/src/designer/qdesigner_actions.h
new file mode 100644
index 000000000..910901bcb
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_actions.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+ // Boolean dynamic property set on actions to
+ // show them in the default toolbar layout
+ static const char *defaultToolbarPropertyName;
+
+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/src/designer/src/designer/qdesigner_appearanceoptions.cpp b/src/designer/src/designer/qdesigner_appearanceoptions.cpp
new file mode 100644
index 000000000..f5b3f3d6d
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_appearanceoptions.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/qdesigner_appearanceoptions.h b/src/designer/src/designer/qdesigner_appearanceoptions.h
new file mode 100644
index 000000000..a6e4f9a49
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_appearanceoptions.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/qdesigner_appearanceoptions.ui b/src/designer/src/designer/qdesigner_appearanceoptions.ui
new file mode 100644
index 000000000..a5582f2ab
--- /dev/null
+++ b/src/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/src/designer/src/designer/qdesigner_formwindow.cpp b/src/designer/src/designer/qdesigner_formwindow.cpp
new file mode 100644
index 000000000..4770d2a58
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_formwindow.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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());
+ updateChanged();
+ }
+ }
+ 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.captureCount() > 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/src/designer/src/designer/qdesigner_formwindow.h b/src/designer/src/designer/qdesigner_formwindow.h
new file mode 100644
index 000000000..5ee4c40b4
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_formwindow.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/qdesigner_pch.h b/src/designer/src/designer/qdesigner_pch.h
new file mode 100644
index 000000000..12eb3f376
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_pch.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/designer/qdesigner_server.cpp b/src/designer/src/designer/qdesigner_server.cpp
new file mode 100644
index 000000000..bffee5b7e
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_server.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/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(const QString &file, files)
+ {
+ QFileInfo fi(file);
+ sSocket->write(fi.absoluteFilePath().toUtf8() + '\n');
+ }
+ sSocket->waitForBytesWritten(3000);
+ sSocket->close();
+ }
+ delete sSocket;
+}
+
+void QDesignerServer::readFromClient()
+{
+ while (m_socket->canReadLine()) {
+ QString 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()
+{
+ 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/src/designer/src/designer/qdesigner_server.h b/src/designer/src/designer/qdesigner_server.h
new file mode 100644
index 000000000..3aeeebdee
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_server.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_SERVER_H
+#define QDESIGNER_SERVER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QTcpServer;
+class QTcpSocket;
+
+class QDesignerServer: public QObject
+{
+ Q_OBJECT
+public:
+ explicit 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:
+ explicit 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/src/designer/src/designer/qdesigner_settings.cpp b/src/designer/src/designer/qdesigner_settings.cpp
new file mode 100644
index 000000000..89bec14f2
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_settings.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = qvariant_cast<QFont>(value(QLatin1String("UI/font")));
+ fontSettings.m_useFont =
+ settings()->value(QLatin1String("UI/useFont"), QVariant(false)).toBool();
+ return fontSettings;
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/designer/qdesigner_settings.h b/src/designer/src/designer/qdesigner_settings.h
new file mode 100644
index 000000000..2391581b8
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_settings.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/qdesigner_toolwindow.cpp b/src/designer/src/designer/qdesigner_toolwindow.cpp
new file mode 100644
index 000000000..376b0afae
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_toolwindow.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/qdesigner_toolwindow.h b/src/designer/src/designer/qdesigner_toolwindow.h
new file mode 100644
index 000000000..1c7b876d1
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_toolwindow.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/qdesigner_workbench.cpp b/src/designer/src/designer/qdesigner_workbench.cpp
new file mode 100644
index 000000000..ffc4b8c7a
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_workbench.cpp
@@ -0,0 +1,1100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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();
+
+#ifndef Q_WS_MAC
+ QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
+ widgetBoxWrapper->action()->setVisible(true);
+ widgetBoxWrapper->setWindowTitle(tr("Widget Box"));
+#endif
+
+ m_mode = DockedMode;
+ const QDesignerSettings settings(m_core);
+ m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows);
+ m_dockedMainWindow->setUnifiedTitleAndToolBarOnMac(true);
+ 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);
+
+ 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 (!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();
+ // Did user specify another (missing) resource path -> set dirty.
+ const bool dirty = editor->property("_q_resourcepathchanged").toBool();
+ editor->setDirty(dirty);
+ 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/src/designer/src/designer/qdesigner_workbench.h b/src/designer/src/designer/qdesigner_workbench.h
new file mode 100644
index 000000000..9266eea60
--- /dev/null
+++ b/src/designer/src/designer/qdesigner_workbench.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/saveformastemplate.cpp b/src/designer/src/designer/saveformastemplate.cpp
new file mode 100644
index 000000000..49ac64ee5
--- /dev/null
+++ b/src/designer/src/designer/saveformastemplate.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/designer/saveformastemplate.h b/src/designer/src/designer/saveformastemplate.h
new file mode 100644
index 000000000..8b0b3ab8e
--- /dev/null
+++ b/src/designer/src/designer/saveformastemplate.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/designer/saveformastemplate.ui b/src/designer/src/designer/saveformastemplate.ui
new file mode 100644
index 000000000..c29ad9ad4
--- /dev/null
+++ b/src/designer/src/designer/saveformastemplate.ui
@@ -0,0 +1,166 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/designer/uifile.icns b/src/designer/src/designer/uifile.icns
new file mode 100644
index 000000000..2473ea4dc
--- /dev/null
+++ b/src/designer/src/designer/uifile.icns
Binary files differ
diff --git a/src/designer/src/designer/versiondialog.cpp b/src/designer/src/designer/versiondialog.cpp
new file mode 100644
index 000000000..63a95e6d7
--- /dev/null
+++ b/src/designer/src/designer/versiondialog.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/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;
+ foreach(const QPoint &pt, hitPoints) {
+ if (!m_path.contains(pt)) {
+ gotIt = false;
+ break;
+ }
+ }
+ if (gotIt) {
+ foreach(const QPoint &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");
+ 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/>"));
+
+ lbl->setText(tr("%1"
+ "<br/>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
+ ).arg(version));
+
+ 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/src/designer/src/designer/versiondialog.h b/src/designer/src/designer/versiondialog.h
new file mode 100644
index 000000000..0e6760092
--- /dev/null
+++ b/src/designer/src/designer/versiondialog.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/components/qdesigner_components.h b/src/designer/src/lib/components/qdesigner_components.h
new file mode 100644
index 000000000..e11afc3ee
--- /dev/null
+++ b/src/designer/src/lib/components/qdesigner_components.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/components/qdesigner_components_global.h b/src/designer/src/lib/components/qdesigner_components_global.h
new file mode 100644
index 000000000..93f3c73ce
--- /dev/null
+++ b/src/designer/src/lib/components/qdesigner_components_global.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/extension/default_extensionfactory.cpp b/src/designer/src/lib/extension/default_extensionfactory.cpp
new file mode 100644
index 000000000..a90886695
--- /dev/null
+++ b/src/designer/src/lib/extension/default_extensionfactory.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/lib/extension/default_extensionfactory.h b/src/designer/src/lib/extension/default_extensionfactory.h
new file mode 100644
index 000000000..370e69aae
--- /dev/null
+++ b/src/designer/src/lib/extension/default_extensionfactory.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/extension/extension.cpp b/src/designer/src/lib/extension/extension.cpp
new file mode 100644
index 000000000..4d325126b
--- /dev/null
+++ b/src/designer/src/lib/extension/extension.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/lib/extension/extension.h b/src/designer/src/lib/extension/extension.h
new file mode 100644
index 000000000..749550324
--- /dev/null
+++ b/src/designer/src/lib/extension/extension.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/extension/extension.pri b/src/designer/src/lib/extension/extension.pri
new file mode 100644
index 000000000..d8ef658f2
--- /dev/null
+++ b/src/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/src/designer/src/lib/extension/extension_global.h b/src/designer/src/lib/extension/extension_global.h
new file mode 100644
index 000000000..25545bb21
--- /dev/null
+++ b/src/designer/src/lib/extension/extension_global.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/extension/qextensionmanager.cpp b/src/designer/src/lib/extension/qextensionmanager.cpp
new file mode 100644
index 000000000..960ae25ed
--- /dev/null
+++ b/src/designer/src/lib/extension/qextensionmanager.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/extension/qextensionmanager.h b/src/designer/src/lib/extension/qextensionmanager.h
new file mode 100644
index 000000000..a387924e6
--- /dev/null
+++ b/src/designer/src/lib/extension/qextensionmanager.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/lib.pro b/src/designer/src/lib/lib.pro
new file mode 100644
index 000000000..3ba6f5235
--- /dev/null
+++ b/src/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|win32-g++*: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, "", true)|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/src/designer/src/lib/lib_pch.h b/src/designer/src/lib/lib_pch.h
new file mode 100644
index 000000000..17c3d8cd6
--- /dev/null
+++ b/src/designer/src/lib/lib_pch.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef __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/src/designer/src/lib/sdk/abstractactioneditor.cpp b/src/designer/src/lib/sdk/abstractactioneditor.cpp
new file mode 100644
index 000000000..f0a7b76a7
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractactioneditor.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractactioneditor.h b/src/designer/src/lib/sdk/abstractactioneditor.h
new file mode 100644
index 000000000..2d4241c23
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractactioneditor.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractbrushmanager.h b/src/designer/src/lib/sdk/abstractbrushmanager.h
new file mode 100644
index 000000000..87b1bf2c0
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractbrushmanager.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractdialoggui.cpp b/src/designer/src/lib/sdk/abstractdialoggui.cpp
new file mode 100644
index 000000000..353f1eae6
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractdialoggui.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractdialoggui_p.h b/src/designer/src/lib/sdk/abstractdialoggui_p.h
new file mode 100644
index 000000000..af3843850
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractdialoggui_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractdnditem.h b/src/designer/src/lib/sdk/abstractdnditem.h
new file mode 100644
index 000000000..229938d75
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractdnditem.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractdnditem.qdoc b/src/designer/src/lib/sdk/abstractdnditem.qdoc
new file mode 100644
index 000000000..958ee2865
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractdnditem.qdoc
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerDnDItemInterface
+ \brief The QDesignerDnDItemInterface class provides an interface that is used to manage items
+ during a drag and drop operation.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ \enum QDesignerDnDItemInterface::DropType
+
+ This enum describes the result of a drag and drop operation.
+
+ \value MoveDrop The item was moved.
+ \value CopyDrop The item was copied.
+*/
+
+/*!
+ \fn QDesignerDnDItemInterface::QDesignerDnDItemInterface()
+
+ Constructs a new interface to a drag and drop item.
+*/
+
+/*!
+ \fn QDesignerDnDItemInterface::~QDesignerDnDItemInterface()
+
+ Destroys the interface to the item.
+*/
+
+/*!
+ \fn DomUI *QDesignerDnDItemInterface::domUi() const
+
+ Returns a user interface object for the item.
+*/
+
+/*!
+ \fn QWidget *QDesignerDnDItemInterface::widget() const
+
+ Returns the widget being copied or moved in the drag and drop operation.
+
+ \sa source()
+*/
+
+/*!
+ \fn QWidget *QDesignerDnDItemInterface::decoration() const
+
+ Returns the widget used to represent the item.
+*/
+
+/*!
+ \fn QPoint QDesignerDnDItemInterface::hotSpot() const
+
+ Returns the cursor's hotspot.
+
+ \sa QDrag::hotSpot()
+*/
+
+/*!
+ \fn DropType QDesignerDnDItemInterface::type() const
+
+ Returns the type of drag and drop operation in progress.
+*/
+
+/*!
+ \fn QWidget *QDesignerDnDItemInterface::source() const
+
+ Returns the widget that is the source of the drag and drop operation; i.e. the original
+ container of the widget being dragged.
+
+ \sa widget()
+*/
diff --git a/src/designer/src/lib/sdk/abstractformeditor.cpp b/src/designer/src/lib/sdk/abstractformeditor.cpp
new file mode 100644
index 000000000..563781631
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformeditor.cpp
@@ -0,0 +1,630 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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>
+
+// Must be done outside of the Qt namespace
+static void initResources()
+{
+ Q_INIT_RESOURCE(shared);
+ Q_INIT_RESOURCE(ClamshellPhone);
+ Q_INIT_RESOURCE(PortableMedia);
+ Q_INIT_RESOURCE(S60_nHD_Touchscreen);
+ Q_INIT_RESOURCE(S60_QVGA_Candybar);
+ Q_INIT_RESOURCE(SmartPhone2);
+ Q_INIT_RESOURCE(SmartPhone);
+ Q_INIT_RESOURCE(SmartPhoneWithButtons);
+ Q_INIT_RESOURCE(TouchscreenPhone);
+}
+
+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/src/designer/src/lib/sdk/abstractformeditor.h b/src/designer/src/lib/sdk/abstractformeditor.h
new file mode 100644
index 000000000..fd83ee55d
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformeditor.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractformeditorplugin.cpp b/src/designer/src/lib/sdk/abstractformeditorplugin.cpp
new file mode 100644
index 000000000..cb7fd8ee9
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformeditorplugin.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/lib/sdk/abstractformeditorplugin.h b/src/designer/src/lib/sdk/abstractformeditorplugin.h
new file mode 100644
index 000000000..a9e01e81a
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformeditorplugin.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractformwindow.cpp b/src/designer/src/lib/sdk/abstractformwindow.cpp
new file mode 100644
index 000000000..7ea450627
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindow.cpp
@@ -0,0 +1,814 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 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 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/src/designer/src/lib/sdk/abstractformwindow.h b/src/designer/src/lib/sdk/abstractformwindow.h
new file mode 100644
index 000000000..36ce4a54c
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindow.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractformwindowcursor.cpp b/src/designer/src/lib/sdk/abstractformwindowcursor.cpp
new file mode 100644
index 000000000..c2611931e
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowcursor.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractformwindowcursor.h b/src/designer/src/lib/sdk/abstractformwindowcursor.h
new file mode 100644
index 000000000..7653450cc
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowcursor.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractformwindowmanager.cpp b/src/designer/src/lib/sdk/abstractformwindowmanager.cpp
new file mode 100644
index 000000000..75c1d4a11
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowmanager.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractformwindowmanager.h b/src/designer/src/lib/sdk/abstractformwindowmanager.h
new file mode 100644
index 000000000..bdd7c99aa
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowmanager.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractformwindowtool.cpp b/src/designer/src/lib/sdk/abstractformwindowtool.cpp
new file mode 100644
index 000000000..b073b22ea
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowtool.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractformwindowtool.h b/src/designer/src/lib/sdk/abstractformwindowtool.h
new file mode 100644
index 000000000..77c499420
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractformwindowtool.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstracticoncache.h b/src/designer/src/lib/sdk/abstracticoncache.h
new file mode 100644
index 000000000..ce2ed9d83
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstracticoncache.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstracticoncache.qdoc b/src/designer/src/lib/sdk/abstracticoncache.qdoc
new file mode 100644
index 000000000..f211c533c
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstracticoncache.qdoc
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerIconCacheInterface
+ \brief The QDesignerIconCacheInterface class provides an interface to \QD's icon cache.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ \fn QDesignerIconCacheInterface::QDesignerIconCacheInterface(QObject *parent)
+
+ Constructs a new interface with the given \a parent.
+*/
+
+/*!
+ \fn QIcon QDesignerIconCacheInterface::nameToIcon(const QString &filePath, const QString &qrcPath)
+
+ Returns the icon associated with the name specified by \a filePath in the resource
+ file specified by \a qrcPath.
+
+ If \a qrcPath refers to a valid resource file, the name used for the file path is a path
+ within those resources; otherwise the file path refers to a local file.
+
+ \sa {The Qt Resource System}, nameToPixmap()
+*/
+
+/*!
+ \fn QPixmap QDesignerIconCacheInterface::nameToPixmap(const QString &filePath, const QString &qrcPath)
+
+ Returns the pixmap associated with the name specified by \a filePath in the resource
+ file specified by \a qrcPath.
+
+ If \a qrcPath refers to a valid resource file, the name used for the file path is a path
+ within those resources; otherwise the file path refers to a local file.
+
+ \sa {The Qt Resource System}, nameToIcon()
+*/
+
+/*!
+ \fn QString QDesignerIconCacheInterface::iconToFilePath(const QIcon &icon) const
+
+ Returns the file path associated with the given \a icon. The file path is a path within
+ an application resources.
+*/
+
+/*!
+ \fn QString QDesignerIconCacheInterface::iconToQrcPath(const QIcon &icon) const
+
+ Returns the path to the resource file that refers to the specified \a icon. The resource
+ path refers to a local file.
+*/
+
+/*!
+ \fn QString QDesignerIconCacheInterface::pixmapToFilePath(const QPixmap &pixmap) const
+
+ Returns the file path associated with the given \a pixmap. The file path is a path within
+ an application resources.
+*/
+
+/*!
+ \fn QString QDesignerIconCacheInterface::pixmapToQrcPath(const QPixmap &pixmap) const
+
+ Returns the path to the resource file that refers to the specified \a pixmap. The resource
+ path refers to a local file.
+*/
+
+/*!
+ \fn QList<QPixmap> QDesignerIconCacheInterface::pixmapList() const
+
+ Returns a list of pixmaps for the icons provided by the icon cache.
+*/
+
+/*!
+ \fn QList<QIcon> QDesignerIconCacheInterface::iconList() const
+
+ Returns a list of icons provided by the icon cache.
+*/
+
+/*!
+ \fn QString QDesignerIconCacheInterface::resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &workingDirectory) const
+
+ Returns a path to a resource specified by the \a filePath within
+ the resource file located at \a qrcPath. If \a workingDirectory is
+ a valid path to a directory, the path returned will be relative to
+ that directory; otherwise an absolute path is returned.
+
+ \omit
+ ### Needs checking
+ \endomit
+*/
diff --git a/src/designer/src/lib/sdk/abstractintegration.cpp b/src/designer/src/lib/sdk/abstractintegration.cpp
new file mode 100644
index 000000000..0c888f651
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractintegration.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractintegration.h"
+#include "abstractformeditor.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+
+// Add 'private' struct as a dynamic property.
+
+static const char privatePropertyC[] = "_q_integrationprivate";
+
+struct QDesignerIntegrationInterfacePrivate {
+ QDesignerIntegrationInterfacePrivate() :
+ headerSuffix(QLatin1String(".h")),
+ headerLowercase(true) {}
+
+ QString headerSuffix;
+ bool headerLowercase;
+};
+
+typedef QSharedPointer<QDesignerIntegrationInterfacePrivate> QDesignerIntegrationInterfacePrivatePtr;
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QDesignerIntegrationInterfacePrivatePtr))
+QT_BEGIN_NAMESPACE
+
+static QDesignerIntegrationInterfacePrivatePtr integrationD(const QObject *o)
+{
+ const QVariant property = o->property(privatePropertyC);
+ Q_ASSERT(qVariantCanConvert<QDesignerIntegrationInterfacePrivatePtr>(property));
+ return qvariant_cast<QDesignerIntegrationInterfacePrivatePtr>(property);
+}
+
+QDesignerIntegrationInterface::QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent),
+ m_core(core)
+{
+ core->setIntegration(this);
+ const QDesignerIntegrationInterfacePrivatePtr d(new QDesignerIntegrationInterfacePrivate);
+ setProperty(privatePropertyC, qVariantFromValue<QDesignerIntegrationInterfacePrivatePtr>(d));
+}
+
+QString QDesignerIntegrationInterface::headerSuffix() const
+{
+ return integrationD(this)->headerSuffix;
+}
+
+void QDesignerIntegrationInterface::setHeaderSuffix(const QString &headerSuffix)
+{
+ integrationD(this)->headerSuffix = headerSuffix;
+}
+
+bool QDesignerIntegrationInterface::isHeaderLowercase() const
+{
+ return integrationD(this)->headerLowercase;
+}
+
+void QDesignerIntegrationInterface::setHeaderLowercase(bool headerLowercase)
+{
+ integrationD(this)->headerLowercase = headerLowercase;
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/sdk/abstractintegration.h b/src/designer/src/lib/sdk/abstractintegration.h
new file mode 100644
index 000000000..9e27f9037
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractintegration.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTINTEGRATION_H
+#define ABSTRACTINTEGRATION_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerIntegrationInterface: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString headerSuffix READ headerSuffix WRITE setHeaderSuffix)
+ Q_PROPERTY(bool headerLowercase READ isHeaderLowercase WRITE setHeaderLowercase)
+
+public:
+ QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+ inline QDesignerFormEditorInterface *core() const;
+
+ virtual QWidget *containerWindow(QWidget *widget) const = 0;
+
+ QString headerSuffix() const;
+ void setHeaderSuffix(const QString &headerSuffix);
+
+ bool isHeaderLowercase() const;
+ void setHeaderLowercase(bool headerLowerCase);
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+inline QDesignerFormEditorInterface *QDesignerIntegrationInterface::core() const
+{ return m_core; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTINTEGRATION_H
diff --git a/src/designer/src/lib/sdk/abstractintrospection.cpp b/src/designer/src/lib/sdk/abstractintrospection.cpp
new file mode 100644
index 000000000..d733588fb
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractintrospection.cpp
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractintrospection_p.h b/src/designer/src/lib/sdk/abstractintrospection_p.h
new file mode 100644
index 000000000..52074b890
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractintrospection_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractlanguage.h b/src/designer/src/lib/sdk/abstractlanguage.h
new file mode 100644
index 000000000..37c0c5de0
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractlanguage.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractmetadatabase.cpp b/src/designer/src/lib/sdk/abstractmetadatabase.cpp
new file mode 100644
index 000000000..061c9aa89
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractmetadatabase.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/lib/sdk/abstractmetadatabase.h b/src/designer/src/lib/sdk/abstractmetadatabase.h
new file mode 100644
index 000000000..1fdc7ef69
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractmetadatabase.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractnewformwidget.cpp b/src/designer/src/lib/sdk/abstractnewformwidget.cpp
new file mode 100644
index 000000000..42d43432e
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractnewformwidget.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractnewformwidget_p.h b/src/designer/src/lib/sdk/abstractnewformwidget_p.h
new file mode 100644
index 000000000..db0c74031
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractnewformwidget_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractobjectinspector.cpp b/src/designer/src/lib/sdk/abstractobjectinspector.cpp
new file mode 100644
index 000000000..d231fce58
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractobjectinspector.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractobjectinspector.h b/src/designer/src/lib/sdk/abstractobjectinspector.h
new file mode 100644
index 000000000..74c6e385a
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractobjectinspector.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractoptionspage_p.h b/src/designer/src/lib/sdk/abstractoptionspage_p.h
new file mode 100644
index 000000000..f6c54ae44
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractoptionspage_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractpromotioninterface.cpp b/src/designer/src/lib/sdk/abstractpromotioninterface.cpp
new file mode 100644
index 000000000..5dd590cb3
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractpromotioninterface.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractpromotioninterface.h b/src/designer/src/lib/sdk/abstractpromotioninterface.h
new file mode 100644
index 000000000..6c60991d8
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractpromotioninterface.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractpropertyeditor.cpp b/src/designer/src/lib/sdk/abstractpropertyeditor.cpp
new file mode 100644
index 000000000..040362c9b
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractpropertyeditor.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractpropertyeditor.h b/src/designer/src/lib/sdk/abstractpropertyeditor.h
new file mode 100644
index 000000000..a8d731631
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractpropertyeditor.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractresourcebrowser.cpp b/src/designer/src/lib/sdk/abstractresourcebrowser.cpp
new file mode 100644
index 000000000..0bb7341ef
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractresourcebrowser.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractresourcebrowser.h"
+
+QT_BEGIN_NAMESPACE
+
+QDesignerResourceBrowserInterface::QDesignerResourceBrowserInterface(QWidget *parent)
+ : QWidget(parent)
+{
+
+}
+
+QDesignerResourceBrowserInterface::~QDesignerResourceBrowserInterface()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/sdk/abstractresourcebrowser.h b/src/designer/src/lib/sdk/abstractresourcebrowser.h
new file mode 100644
index 000000000..836912d9a
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractresourcebrowser.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractsettings_p.h b/src/designer/src/lib/sdk/abstractsettings_p.h
new file mode 100644
index 000000000..6637d1ae5
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractsettings_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/abstractwidgetbox.cpp b/src/designer/src/lib/sdk/abstractwidgetbox.cpp
new file mode 100644
index 000000000..6b23c606a
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetbox.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractwidgetbox.h b/src/designer/src/lib/sdk/abstractwidgetbox.h
new file mode 100644
index 000000000..cf1cb1b2e
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetbox.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractwidgetdatabase.cpp b/src/designer/src/lib/sdk/abstractwidgetdatabase.cpp
new file mode 100644
index 000000000..f48b10030
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetdatabase.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/abstractwidgetdatabase.h b/src/designer/src/lib/sdk/abstractwidgetdatabase.h
new file mode 100644
index 000000000..7ea5db8a1
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetdatabase.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/abstractwidgetfactory.cpp b/src/designer/src/lib/sdk/abstractwidgetfactory.cpp
new file mode 100644
index 000000000..769db175c
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetfactory.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/lib/sdk/abstractwidgetfactory.h b/src/designer/src/lib/sdk/abstractwidgetfactory.h
new file mode 100644
index 000000000..a5c2ab16d
--- /dev/null
+++ b/src/designer/src/lib/sdk/abstractwidgetfactory.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/dynamicpropertysheet.h b/src/designer/src/lib/sdk/dynamicpropertysheet.h
new file mode 100644
index 000000000..478f3a4a6
--- /dev/null
+++ b/src/designer/src/lib/sdk/dynamicpropertysheet.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/dynamicpropertysheet.qdoc b/src/designer/src/lib/sdk/dynamicpropertysheet.qdoc
new file mode 100644
index 000000000..e077e714d
--- /dev/null
+++ b/src/designer/src/lib/sdk/dynamicpropertysheet.qdoc
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerDynamicPropertySheetExtension
+
+ \brief The QDesignerDynamicPropertySheetExtension class allows you to
+ manipulate a widget's dynamic properties in Qt Designer's property editor.
+
+ \sa QDesignerPropertySheetExtension, {QObject#Dynamic Properties}{Dynamic Properties}
+
+ \inmodule QtDesigner
+ \since 4.3
+*/
+
+/*!
+ \fn QDesignerDynamicPropertySheetExtension::~QDesignerDynamicPropertySheetExtension()
+
+ Destroys the dynamic property sheet extension.
+*/
+
+/*!
+ \fn bool QDesignerDynamicPropertySheetExtension::dynamicPropertiesAllowed() const
+
+ Returns true if the widget supports dynamic properties; otherwise returns false.
+*/
+
+/*!
+ \fn int QDesignerDynamicPropertySheetExtension::addDynamicProperty(const QString &propertyName, const QVariant &value)
+
+ Adds a dynamic property named \a propertyName and sets its value to \a value.
+ Returns the index of the property if it was added successfully; otherwise returns -1 to
+ indicate failure.
+*/
+
+/*!
+ \fn bool QDesignerDynamicPropertySheetExtension::removeDynamicProperty(int index)
+
+ Removes the dynamic property at the given \a index.
+ Returns true if the operation succeeds; otherwise returns false.
+*/
+
+/*!
+ \fn bool QDesignerDynamicPropertySheetExtension::isDynamicProperty(int index) const
+
+ Returns true if the property at the given \a index is a dynamic property; otherwise
+ returns false.
+*/
+
+/*!
+ \fn bool QDesignerDynamicPropertySheetExtension::canAddDynamicProperty(const QString &propertyName) const
+
+ Returns true if \a propertyName is a valid, unique name for a dynamic
+ property; otherwise returns false.
+
+*/
diff --git a/src/designer/src/lib/sdk/extrainfo.cpp b/src/designer/src/lib/sdk/extrainfo.cpp
new file mode 100644
index 000000000..9c272dc16
--- /dev/null
+++ b/src/designer/src/lib/sdk/extrainfo.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/sdk/extrainfo.h b/src/designer/src/lib/sdk/extrainfo.h
new file mode 100644
index 000000000..10034e9a6
--- /dev/null
+++ b/src/designer/src/lib/sdk/extrainfo.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/layoutdecoration.h b/src/designer/src/lib/sdk/layoutdecoration.h
new file mode 100644
index 000000000..4a6577059
--- /dev/null
+++ b/src/designer/src/lib/sdk/layoutdecoration.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/layoutdecoration.qdoc b/src/designer/src/lib/sdk/layoutdecoration.qdoc
new file mode 100644
index 000000000..9456e380d
--- /dev/null
+++ b/src/designer/src/lib/sdk/layoutdecoration.qdoc
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerLayoutDecorationExtension
+ \brief The QDesignerLayoutDecorationExtension class provides an extension to a layout in \QD.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ \enum QDesignerLayoutDecorationExtension::InsertMode
+
+ This enum describes the modes that are used to insert items into a layout.
+
+ \value InsertWidgetMode Widgets are inserted into empty cells in a layout.
+ \value InsertRowMode Whole rows are inserted into a vertical or grid layout.
+ \value InsertColumnMode Whole columns are inserted into a horizontal or grid layout.
+*/
+
+/*!
+ \fn virtual QDesignerLayoutDecorationExtension::~QDesignerLayoutDecorationExtension()
+
+ Destroys the extension.
+*/
+
+/*!
+ \fn virtual QList<QWidget*> QDesignerLayoutDecorationExtension::widgets(QLayout *layout) const
+
+ Returns the widgets that are managed by the given \a layout.
+
+ \sa insertWidget(), removeWidget()
+*/
+
+/*!
+ \fn QRect QDesignerLayoutDecorationExtension::itemInfo(int index) const
+
+ Returns the rectangle covered by the item at the given \a index in the layout.
+*/
+
+/*!
+ \fn int QDesignerLayoutDecorationExtension::indexOf(QWidget *widget) const
+
+ Returns the index of the specified \a widget in the layout.
+*/
+
+/*!
+ \fn int QDesignerLayoutDecorationExtension::indexOf(QLayoutItem *item) const
+
+ Returns the index of the specified layout \a item.
+*/
+
+/*!
+ \fn QDesignerLayoutDecorationExtension::InsertMode QDesignerLayoutDecorationExtension::currentInsertMode() const
+
+ Returns the current insertion mode.
+*/
+
+/*!
+ \fn int QDesignerLayoutDecorationExtension::currentIndex() const
+
+ Returns the current index in the layout.
+*/
+
+/*!
+ \fn QPair<int, int> QDesignerLayoutDecorationExtension::currentCell() const
+
+ Returns a pair containing the row and column of the current cell in the layout.
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::insertWidget(QWidget *widget, const QPair<int, int> &cell)
+
+ Inserts the given \a widget into the specified \a cell in the layout.
+
+ \sa removeWidget()
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::removeWidget(QWidget *widget)
+
+ Removes the specified \a widget from the layout.
+
+ \sa insertWidget()
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::insertRow(int row)
+
+ Inserts a new row into the form at the position specified by \a row.
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::insertColumn(int column)
+
+ Inserts a new column into the form at the position specified by \a column.
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::simplify()
+
+ Simplifies the layout by removing unnecessary empty rows and columns, and by changing the
+ number of rows or columns spanned by widgets.
+*/
+
+/*!
+ \fn int QDesignerLayoutDecorationExtension::findItemAt(const QPoint &position) const
+
+ Returns the index of the item in the layout that covers the given \a position.
+*/
+
+/*!
+ \fn int QDesignerLayoutDecorationExtension::findItemAt(int row, int column) const
+
+ Returns the item in the layout that occupies the specified \a row and \a column in the layout.
+
+ Currently, this only applies to grid layouts.
+*/
+
+/*!
+ \fn void QDesignerLayoutDecorationExtension::adjustIndicator(const QPoint &position, int index)
+
+ Adjusts the indicator for the item specified by \a index so that
+ it lies at the given \a position on the form.
+*/
diff --git a/src/designer/src/lib/sdk/membersheet.h b/src/designer/src/lib/sdk/membersheet.h
new file mode 100644
index 000000000..b1ff1a4c6
--- /dev/null
+++ b/src/designer/src/lib/sdk/membersheet.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/membersheet.qdoc b/src/designer/src/lib/sdk/membersheet.qdoc
new file mode 100644
index 000000000..57a366407
--- /dev/null
+++ b/src/designer/src/lib/sdk/membersheet.qdoc
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerMemberSheetExtension
+
+ \brief The QDesignerMemberSheetExtension class allows you to
+ manipulate a widget's member functions which is displayed when
+ configuring connections using Qt Designer's mode for editing
+ signals and slots.
+
+ \inmodule QtDesigner
+
+ QDesignerMemberSheetExtension is a collection of functions that is
+ typically used to query a widget's member functions, and to
+ manipulate the member functions' appearance in \QD's signals and
+ slots editing mode. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 2
+
+ 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.
+
+ The member sheet (and any other extension), can be retrieved by
+ querying \QD's extension manager using the qt_extension()
+ function. When you want to release the extension, you only need to
+ delete the pointer.
+
+ All widgets have a default member sheet used in \QD's signals and
+ slots editing mode with the widget's member functions. But
+ QDesignerMemberSheetExtension also provides an interface for
+ creating custom member sheet extensions.
+
+ \warning \QD uses the QDesignerMemberSheetExtension to facilitate
+ the signal and slot editing mode. Whenever a connection between
+ two widgets is requested, \QD will query for the widgets' member
+ sheet extensions. If a widget has an implemented member sheet
+ extension, this extension will override the default member sheet.
+
+ To create a member sheet extension, your extension class must
+ inherit from both QObject and QDesignerMemberSheetExtension. Then,
+ since we are implementing an interface, we must ensure that it's
+ made known to the meta object system using the Q_INTERFACES()
+ macro:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 3
+
+ This enables \QD to use qobject_cast() to query for
+ supported interfaces using nothing but a QObject pointer.
+
+ In \QD the extensions are not created until they are
+ required. For that reason, when implementing a member sheet
+ 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 a widget's member sheet 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 a member sheet
+ extension for that widget, is found. This factory will then make
+ an instance of the extension. If no such factory is found, \QD
+ will use the default member sheet.
+
+ 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 multi page container, a
+ member sheet, a property sheet or a task menu.
+
+ The QExtensionFactory class provides a standard extension
+ factory, and can also be used as an interface for custom
+ extension factories. You can either create a new
+ QExtensionFactory and reimplement the
+ QExtensionFactory::createExtension() function. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 4
+
+ Or you can use an existing factory, expanding the
+ QExtensionFactory::createExtension() function to make the factory
+ able to create a member sheet extension as well. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 5
+
+ For a complete example using an extension class, see \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, QExtensionManager, {Creating Custom Widget
+ Extensions}
+*/
+
+/*!
+ \fn QDesignerMemberSheetExtension::~QDesignerMemberSheetExtension()
+
+ Destroys the member sheet extension.
+*/
+
+/*!
+ \fn int QDesignerMemberSheetExtension::count() const
+
+ Returns the extension's number of member functions.
+*/
+
+/*!
+ \fn int QDesignerMemberSheetExtension::indexOf(const QString &name) const
+
+ Returns the index of the member function specified by the given \a
+ name.
+
+ \sa memberName()
+*/
+
+/*!
+ \fn QString QDesignerMemberSheetExtension::memberName(int index) const
+
+ Returns the name of the member function with the given \a index.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn QString QDesignerMemberSheetExtension::memberGroup(int index) const
+
+ Returns the name of the member group specified for the function
+ with the given \a index.
+
+ \sa indexOf(), setMemberGroup()
+*/
+
+/*!
+ \fn void QDesignerMemberSheetExtension::setMemberGroup(int index, const QString &group)
+
+ Sets the member group of the member function with the given \a
+ index, to \a group.
+
+ \sa indexOf(), memberGroup()
+*/
+
+/*!
+ \fn bool QDesignerMemberSheetExtension::isVisible(int index) const
+
+ Returns true if the member function with the given \a index is
+ visible in \QD's signal and slot editor, otherwise false.
+
+ \sa indexOf(), setVisible()
+*/
+
+/*!
+ \fn void QDesignerMemberSheetExtension::setVisible(int index, bool visible)
+
+ If \a visible is true, the member function with the given \a index
+ is visible in \QD's signals and slots editing mode; otherwise the
+ member function is hidden.
+
+ \sa indexOf(), isVisible()
+*/
+
+/*!
+ \fn virtual bool QDesignerMemberSheetExtension::isSignal(int index) const
+
+ Returns true if the member function with the given \a index is a
+ signal, otherwise false.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn bool QDesignerMemberSheetExtension::isSlot(int index) const
+
+ Returns true if the member function with the given \a index is a
+ slot, otherwise false.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn bool QDesignerMemberSheetExtension::inheritedFromWidget(int index) const
+
+ Returns true if the member function with the given \a index is
+ inherited from QWidget, otherwise false.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn QString QDesignerMemberSheetExtension::declaredInClass(int index) const
+
+ Returns the name of the class in which the member function with
+ the given \a index is declared.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn QString QDesignerMemberSheetExtension::signature(int index) const
+
+ Returns the signature of the member function with the given \a
+ index.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn QList<QByteArray> QDesignerMemberSheetExtension::parameterTypes(int index) const
+
+ Returns the parameter types of the member function with the given
+ \a index, as a QByteArray list.
+
+ \sa indexOf(), parameterNames()
+*/
+
+/*!
+ \fn QList<QByteArray> QDesignerMemberSheetExtension::parameterNames(int index) const
+
+ Returns the parameter names of the member function with the given
+ \a index, as a QByteArray list.
+
+ \sa indexOf(), parameterTypes()
+*/
diff --git a/src/designer/src/lib/sdk/propertysheet.h b/src/designer/src/lib/sdk/propertysheet.h
new file mode 100644
index 000000000..36a0e4e1b
--- /dev/null
+++ b/src/designer/src/lib/sdk/propertysheet.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/propertysheet.qdoc b/src/designer/src/lib/sdk/propertysheet.qdoc
new file mode 100644
index 000000000..becc74b0e
--- /dev/null
+++ b/src/designer/src/lib/sdk/propertysheet.qdoc
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerPropertySheetExtension
+
+ \brief The QDesignerPropertySheetExtension class allows you to
+ manipulate a widget's properties which is displayed in Qt
+ Designer's property editor.
+
+ \sa QDesignerDynamicPropertySheetExtension
+
+ \inmodule QtDesigner
+
+ QDesignerPropertySheetExtension provides a collection of functions that
+ are typically used to query a widget's properties, and to
+ manipulate the properties' appearance in the property editor. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 15
+
+ Note that if you change the value of a property using the
+ QDesignerPropertySheetExtension::setProperty() function, the undo
+ stack is not updated. To ensure that a property's value can be
+ reverted using the undo stack, you must use the
+ QDesignerFormWindowCursorInterface::setProperty() function, or its
+ buddy \l
+ {QDesignerFormWindowCursorInterface::setWidgetProperty()}{setWidgetProperty()},
+ instead.
+
+ 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.
+
+ The property sheet, or any other extension, can be retrieved by
+ querying \QD's extension manager using the qt_extension()
+ function. When you want to release the extension, you only need to
+ delete the pointer.
+
+ All widgets have a default property sheet which populates \QD's
+ property editor with the widget's properties (i.e the ones defined
+ with the Q_PROPERTY() macro). But QDesignerPropertySheetExtension
+ also provides an interface for creating custom property sheet
+ extensions.
+
+ \warning \QD uses the QDesignerPropertySheetExtension to feed its
+ property editor. Whenever a widget is selected in its workspace,
+ \QD will query for the widget's property sheet extension. If the
+ selected widget has an implemented property sheet extension, this
+ extension will override the default property sheet.
+
+ To create a property sheet extension, your extension class must
+ inherit from both QObject and
+ QDesignerPropertySheetExtension. Then, since we are implementing
+ an interface, we must ensure that it's made known to the meta
+ object system using the Q_INTERFACES() macro:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 16
+
+ This enables \QD to use qobject_cast() to query for supported
+ interfaces using nothing but a QObject pointer.
+
+ In \QD the extensions are not created until they are
+ required. For that reason, when implementing a property sheet
+ 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 a property sheet 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 a property
+ sheet extension for the selected widget, is found. This factory
+ will then make an instance of the extension. If no such factory
+ can be found, \QD will use the default property sheet.
+
+ There are four available types of extensions in \QD:
+ 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.
+
+ The QExtensionFactory class provides a standard extension factory,
+ and can also be used as an interface for custom extension
+ factories. You can either create a new QExtensionFactory and
+ reimplement the QExtensionFactory::createExtension() function. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 17
+
+ Or you can use an existing factory, expanding the
+ QExtensionFactory::createExtension() function to make the factory
+ able to create a property sheet extension extension as well. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 18
+
+ For a complete example using an extension 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, QExtensionManager, {Creating Custom Widget
+ Extensions}
+*/
+
+/*!
+ \fn QDesignerPropertySheetExtension::~QDesignerPropertySheetExtension()
+
+ Destroys the property sheet extension.
+*/
+
+/*!
+ \fn int QDesignerPropertySheetExtension::count() const
+
+ Returns the selected widget's number of properties.
+*/
+
+/*!
+ \fn int QDesignerPropertySheetExtension::indexOf(const QString &name) const
+
+ Returns the index for a given property \a name.
+
+ \sa propertyName()
+*/
+
+/*!
+ \fn QString QDesignerPropertySheetExtension::propertyName(int index) const
+
+ Returns the name of the property at the given \a index.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn QString QDesignerPropertySheetExtension::propertyGroup(int index) const
+
+ Returns the property group for the property at the given \a index.
+
+ \QD's property editor supports property groups, i.e. sections of
+ related properties. A property can be related to a group using the
+ setPropertyGroup() function. The default group of any property is
+ the name of the class that defines it. For example, the
+ QObject::objectName property appears within the QObject property
+ group.
+
+ \sa indexOf(), setPropertyGroup()
+*/
+
+/*!
+ \fn void QDesignerPropertySheetExtension::setPropertyGroup(int index, const QString &group)
+
+ Sets the property group for the property at the given \a index to
+ \a group.
+
+ Relating a property to a group makes it appear within that group's
+ section in the property editor. The default property group of any
+ property is the name of the class that defines it. For example,
+ the QObject::objectName property appears within the QObject
+ property group.
+
+ \sa indexOf(), property(), propertyGroup()
+*/
+
+/*!
+ \fn bool QDesignerPropertySheetExtension::hasReset(int index) const
+
+ Returns true if the property at the given \a index has a reset
+ button in \QD's property editor, otherwise false.
+
+ \sa indexOf(), reset()
+*/
+
+/*!
+ \fn bool QDesignerPropertySheetExtension::reset(int index)
+
+ Resets the value of the property at the given \a index, to the
+ default value. Returns true if a default value could be found, otherwise false.
+
+ \sa indexOf(), hasReset(), isChanged()
+*/
+
+/*!
+ \fn bool QDesignerPropertySheetExtension::isVisible(int index) const
+
+ Returns true if the property at the given \a index is visible in
+ \QD's property editor, otherwise false.
+
+ \sa indexOf(), setVisible()
+*/
+
+/*!
+ \fn void QDesignerPropertySheetExtension::setVisible(int index, bool visible)
+
+ If \a visible is true, the property at the given \a index is
+ visible in \QD's property editor; otherwise the property is
+ hidden.
+
+ \sa indexOf(), isVisible()
+*/
+
+/*!
+ \fn bool QDesignerPropertySheetExtension::isAttribute(int index) const
+
+ Returns true if the property at the given \a index is an attribute,
+ which will be \e excluded from the UI file, otherwise false.
+
+ \sa indexOf(), setAttribute()
+*/
+
+/*!
+ \fn void QDesignerPropertySheetExtension::setAttribute(int index, bool attribute)
+
+ If \a attribute is true, the property at the given \a index is
+ made an attribute which will be \e excluded from the UI file;
+ otherwise it will be included.
+
+ \sa indexOf(), isAttribute()
+*/
+
+/*!
+ \fn QVariant QDesignerPropertySheetExtension::property(int index) const
+
+ Returns the value of the property at the given \a index.
+
+ \sa indexOf(), setProperty(), propertyGroup()
+*/
+
+/*!
+ \fn void QDesignerPropertySheetExtension::setProperty(int index, const QVariant &value)
+
+ Sets the \a value of the property at the given \a index.
+
+ \warning If you change the value of a property using this
+ function, the undo stack is not updated. To ensure that a
+ property's value can be reverted using the undo stack, you must
+ use the QDesignerFormWindowCursorInterface::setProperty()
+ function, or its buddy \l
+ {QDesignerFormWindowCursorInterface::setWidgetProperty()}{setWidgetProperty()},
+ instead.
+
+ \sa indexOf(), property(), propertyGroup()
+*/
+
+/*!
+ \fn bool QDesignerPropertySheetExtension::isChanged(int index) const
+
+ Returns true if the value of the property at the given \a index
+ differs from the property's default value, otherwise false.
+
+ \sa indexOf(), setChanged(), reset()
+*/
+
+/*!
+ \fn void QDesignerPropertySheetExtension::setChanged(int index, bool changed)
+
+ Sets whether the property at the given \a index is different from
+ its default value, or not, depending on the \a changed parameter.
+
+ \sa indexOf(), isChanged()
+*/
diff --git a/src/designer/src/lib/sdk/script.cpp b/src/designer/src/lib/sdk/script.cpp
new file mode 100644
index 000000000..0723b6dcd
--- /dev/null
+++ b/src/designer/src/lib/sdk/script.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 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 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 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/src/designer/src/lib/sdk/script_p.h b/src/designer/src/lib/sdk/script_p.h
new file mode 100644
index 000000000..81b588ccb
--- /dev/null
+++ b/src/designer/src/lib/sdk/script_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/sdk/sdk.pri b/src/designer/src/lib/sdk/sdk.pri
new file mode 100644
index 000000000..bc46a1edb
--- /dev/null
+++ b/src/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/src/designer/src/lib/sdk/sdk_global.h b/src/designer/src/lib/sdk/sdk_global.h
new file mode 100644
index 000000000..b2a0f5767
--- /dev/null
+++ b/src/designer/src/lib/sdk/sdk_global.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/taskmenu.h b/src/designer/src/lib/sdk/taskmenu.h
new file mode 100644
index 000000000..94db7bc26
--- /dev/null
+++ b/src/designer/src/lib/sdk/taskmenu.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/sdk/taskmenu.qdoc b/src/designer/src/lib/sdk/taskmenu.qdoc
new file mode 100644
index 000000000..c5a379539
--- /dev/null
+++ b/src/designer/src/lib/sdk/taskmenu.qdoc
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QDesignerTaskMenuExtension
+ \brief The QDesignerTaskMenuExtension class allows you to add custom
+ menu entries to Qt Designer's task menu.
+ \inmodule QtDesigner
+
+ QDesignerTaskMenuExtension provides an interface for creating
+ custom task menu extensions. It is typically used to create task
+ menu entries that are specific to a plugin in \QD.
+
+ \QD uses the QDesignerTaskMenuExtension to feed its task
+ menu. Whenever a task menu is requested, \QD will query
+ for the selected widget's task menu extension.
+
+ \image taskmenuextension-example-faded.png
+
+ A task menu extension is a collection of QActions. The actions
+ appear as entries in the task menu when the plugin with the
+ specified extension is selected. The image above shows the custom
+ \gui {Edit State...} action which appears in addition to \QD's
+ default task menu entries: \gui Cut, \gui Copy, \gui Paste etc.
+
+ To create a custom task menu extension, your extension class must
+ inherit from both QObject and QDesignerTaskMenuExtension. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 9
+
+ Since we are implementing an interface, we must ensure that it
+ is made known to the meta-object system using the Q_INTERFACES()
+ macro. This enables \QD to use the qobject_cast() function to
+ query for supported interfaces using nothing but a QObject
+ pointer.
+
+ You must reimplement the taskActions() function to return a list
+ of actions that will be included in \QD task menu. Optionally, you
+ can reimplement the preferredEditAction() function to set the
+ action that is invoked when selecting your plugin and pressing
+ \key F2. The preferred edit action must be one of the actions
+ returned by taskActions() and, if it's not defined, pressing the
+ \key F2 key will simply be ignored.
+
+ In \QD, extensions are not created until they are required. A
+ task menu extension, for example, is created when you click the
+ right mouse button over a widget in \QD's workspace. For that
+ reason you must also construct an extension factory, using either
+ QExtensionFactory or a subclass, and register it using \QD's
+ \l {QExtensionManager}{extension manager}.
+
+ When a task menu extension is required, \QD's \l
+ {QExtensionManager}{extension manager} will run through all its
+ registered factories calling QExtensionFactory::createExtension()
+ for each until it finds one that is able to create a task menu
+ extension for the selected widget. 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.
+
+ The QExtensionFactory class provides a standard extension factory,
+ and can also be used as an interface for custom extension
+ factories. You can either create a new QExtensionFactory and
+ reimplement the QExtensionFactory::createExtension() function. For
+ example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 10
+
+ Or you can use an existing factory, expanding the
+ QExtensionFactory::createExtension() function to make the factory
+ able to create a task menu extension as well. For example:
+
+ \snippet doc/src/snippets/code/doc_src_qtdesigner.cpp 11
+
+ For a complete example using the QDesignerTaskMenuExtension class,
+ see the \l {designer/taskmenuextension}{Task Menu Extension
+ example}. The example shows how to create a custom widget plugin
+ for \QD, and how to to use the QDesignerTaskMenuExtension
+ class to add custom items to \QD's task menu.
+
+ \sa QExtensionFactory, QExtensionManager, {Creating Custom Widget
+ Extensions}
+*/
+
+/*!
+ \fn QDesignerTaskMenuExtension::~QDesignerTaskMenuExtension()
+
+ Destroys the task menu extension.
+*/
+
+/*!
+ \fn QAction *QDesignerTaskMenuExtension::preferredEditAction() const
+
+ Returns the action that is invoked when selecting a plugin with
+ the specified extension and pressing \key F2.
+
+ The action must be one of the actions returned by taskActions().
+*/
+
+/*!
+ \fn QList<QAction*> QDesignerTaskMenuExtension::taskActions() const
+
+ Returns the task menu extension as a list of actions which will be
+ included in \QD's task menu when a plugin with the specified
+ extension is selected.
+
+ The function must be reimplemented to add actions to the list.
+*/
diff --git a/src/designer/src/lib/shared/actioneditor.cpp b/src/designer/src/lib/shared/actioneditor.cpp
new file mode 100644
index 000000000..fb882c30b
--- /dev/null
+++ b/src/designer/src/lib/shared/actioneditor.cpp
@@ -0,0 +1,823 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+ QIcon documentNewIcon = QIcon::fromTheme("document-new", createIconSet(QLatin1String("filenew.png")));
+ m_actionNew->setIcon(documentNewIcon);
+ 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()));
+ QIcon editCutIcon = QIcon::fromTheme("edit-cut", createIconSet(QLatin1String("editcut.png")));
+ m_actionCut->setIcon(editCutIcon);
+
+ m_actionCopy->setEnabled(false);
+ connect(m_actionCopy, SIGNAL(triggered()), this, SLOT(slotCopy()));
+ QIcon editCopyIcon = QIcon::fromTheme("edit-copy", createIconSet(QLatin1String("editcopy.png")));
+ m_actionCopy->setIcon(editCopyIcon);
+ toolbar->addAction(m_actionCopy);
+
+ connect(m_actionPaste, SIGNAL(triggered()), this, SLOT(slotPaste()));
+ QIcon editPasteIcon = QIcon::fromTheme("edit-paste", createIconSet(QLatin1String("editpaste.png")));
+ m_actionPaste->setIcon(editPasteIcon);
+ toolbar->addAction(m_actionPaste);
+
+ m_actionEdit->setEnabled(false);
+ connect(m_actionEdit, SIGNAL(triggered()), this, SLOT(editCurrentAction()));
+
+ connect(m_actionNavigateToSlot, SIGNAL(triggered()), this, SLOT(navigateToSlotCurrentAction()));
+
+ QIcon editDeleteIcon = QIcon::fromTheme("edit-delete", createIconSet(QLatin1String("editdelete.png")));
+ m_actionDelete->setIcon(editDeleteIcon);
+ 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);
+ QIcon configureIcon = QIcon::fromTheme("document-properties", createIconSet(QLatin1String("configure.png")));
+ configureAction->setIcon(configureIcon);
+ 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 = m_formWindow->mainContainer()->findChildren<QAction*>();
+ 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 = formWindow->mainContainer()->findChildren<QAction*>();
+ 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 initial 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.value().isEmpty())
+ setInitialProperty(sheet, QLatin1String(shortcutPropertyC), QVariant::fromValue(actionData.keysequence));
+
+ sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), QVariant::fromValue(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.isEmpty()) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(action, iconProperty);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, iconProperty, QVariant::fromValue(newIcon));
+ return cmd;
+}
+
+// return a FormWindow command to apply a QKeySequence or a reset command
+// in case it is empty.
+
+static QDesignerFormWindowCommand *setKeySequencePropertyCommand(const PropertySheetKeySequenceValue &ks, QAction *action, QDesignerFormWindowInterface *fw)
+{
+ const QString shortcutProperty = QLatin1String(shortcutPropertyC);
+ if (ks.value().isEmpty()) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(action, shortcutProperty);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, shortcutProperty, QVariant::fromValue(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 = qvariant_cast<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 = qvariant_cast<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC))));
+ oldActionData.keysequence = ActionModel::actionShortCut(sheet);
+ 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 =
+ qvariant_cast<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/src/designer/src/lib/shared/actioneditor_p.h b/src/designer/src/lib/shared/actioneditor_p.h
new file mode 100644
index 000000000..ffeae5846
--- /dev/null
+++ b/src/designer/src/lib/shared/actioneditor_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/actionprovider_p.h b/src/designer/src/lib/shared/actionprovider_p.h
new file mode 100644
index 000000000..ce8a1795e
--- /dev/null
+++ b/src/designer/src/lib/shared/actionprovider_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 && w->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/src/designer/src/lib/shared/actionrepository.cpp b/src/designer/src/lib/shared/actionrepository.cpp
new file mode 100644
index 000000000..d7701cb9c
--- /dev/null
+++ b/src/designer/src/lib/shared/actionrepository.cpp
@@ -0,0 +1,665 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "actionrepository_p.h"
+#include "qtresourceview_p.h"
+#include "iconloader_p.h"
+#include "qdesigner_utils_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));
+}
+
+namespace qdesigner_internal {
+
+// ----------- ActionModel
+ActionModel::ActionModel(QWidget *parent ) :
+ QStandardItemModel(parent),
+ m_emptyIcon(emptyIcon()),
+ 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()), m_emptyIcon, 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;
+ itemData.setValue(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, m_emptyIcon, 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.
+PropertySheetKeySequenceValue ActionModel::actionShortCut(QDesignerFormEditorInterface *core, QAction *action)
+{
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), action);
+ if (!sheet)
+ return PropertySheetKeySequenceValue();
+ return actionShortCut(sheet);
+}
+
+PropertySheetKeySequenceValue ActionModel::actionShortCut(const QDesignerPropertySheetExtension *sheet)
+{
+ const int index = sheet->indexOf(QLatin1String("shortcut"));
+ if (index == -1)
+ return PropertySheetKeySequenceValue();
+ return qvariant_cast<PropertySheetKeySequenceValue>(sheet->property(index));
+}
+
+void ActionModel::setItems(QDesignerFormEditorInterface *core, QAction *action,
+ const QIcon &defaultIcon,
+ 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());
+ QIcon icon = action->icon();
+ if (icon.isNull())
+ icon = defaultIcon;
+ item->setIcon(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).value().toString(QKeySequence::NativeText);
+ 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));
+ QTreeView::currentChanged(current, previous);
+}
+
+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));
+ QListView::currentChanged(current, previous);
+}
+
+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/src/designer/src/lib/shared/actionrepository_p.h b/src/designer/src/lib/shared/actionrepository_p.h
new file mode 100644
index 000000000..c2393cb0b
--- /dev/null
+++ b/src/designer/src/lib/shared/actionrepository_p.h
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+class QPixmap;
+
+class QDesignerFormEditorInterface;
+class QDesignerPropertySheetExtension;
+
+namespace qdesigner_internal {
+
+class PropertySheetKeySequenceValue;
+
+// 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);
+
+ // Retrieve shortcut via property sheet as it is a fake property
+ static PropertySheetKeySequenceValue actionShortCut(QDesignerFormEditorInterface *core, QAction *action);
+ static PropertySheetKeySequenceValue actionShortCut(const QDesignerPropertySheetExtension *ps);
+
+signals:
+ void resourceImageDropped(const QString &path, QAction *action);
+
+private:
+ typedef QList<QStandardItem *> QStandardItemList;
+
+ void initializeHeaders();
+ static void setItems(QDesignerFormEditorInterface *core, QAction *a,
+ const QIcon &defaultIcon,
+ QStandardItemList &sl);
+
+ const QIcon m_emptyIcon;
+
+ 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/src/designer/src/lib/shared/addlinkdialog.ui b/src/designer/src/lib/shared/addlinkdialog.ui
new file mode 100644
index 000000000..3171159f9
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/codedialog.cpp b/src/designer/src/lib/shared/codedialog.cpp
new file mode 100644
index 000000000..2420aa54a
--- /dev/null
+++ b/src/designer/src/lib/shared/codedialog.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/codedialog_p.h b/src/designer/src/lib/shared/codedialog_p.h
new file mode 100644
index 000000000..bed7e224f
--- /dev/null
+++ b/src/designer/src/lib/shared/codedialog_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/connectionedit.cpp b/src/designer/src/lib/shared/connectionedit.cpp
new file mode 100644
index 000000000..5f5085c17
--- /dev/null
+++ b/src/designer/src/lib/shared/connectionedit.cpp
@@ -0,0 +1,1612 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "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 = widget->findChildren<QWidget*>();
+ 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 = m_bg_widget->findChild<QObject*>(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 = m_bg_widget->findChild<QObject*>(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/src/designer/src/lib/shared/connectionedit_p.h b/src/designer/src/lib/shared/connectionedit_p.h
new file mode 100644
index 000000000..553fbe188
--- /dev/null
+++ b/src/designer/src/lib/shared/connectionedit_p.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 };
+ explicit 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/src/designer/src/lib/shared/csshighlighter.cpp b/src/designer/src/lib/shared/csshighlighter.cpp
new file mode 100644
index 000000000..4d833b2ab
--- /dev/null
+++ b/src/designer/src/lib/shared/csshighlighter.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/csshighlighter_p.h b/src/designer/src/lib/shared/csshighlighter_p.h
new file mode 100644
index 000000000..f8be2f2c0
--- /dev/null
+++ b/src/designer/src/lib/shared/csshighlighter_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/defaultgradients.xml b/src/designer/src/lib/shared/defaultgradients.xml
new file mode 100644
index 000000000..70559ad12
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/deviceprofile.cpp b/src/designer/src/lib/shared/deviceprofile.cpp
new file mode 100644
index 000000000..3228cab5f
--- /dev/null
+++ b/src/designer/src/lib/shared/deviceprofile.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/deviceprofile_p.h b/src/designer/src/lib/shared/deviceprofile_p.h
new file mode 100644
index 000000000..9d0cdbd51
--- /dev/null
+++ b/src/designer/src/lib/shared/deviceprofile_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/dialoggui.cpp b/src/designer/src/lib/shared/dialoggui.cpp
new file mode 100644
index 000000000..3aa4c796d
--- /dev/null
+++ b/src/designer/src/lib/shared/dialoggui.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/dialoggui_p.h b/src/designer/src/lib/shared/dialoggui_p.h
new file mode 100644
index 000000000..c78eea2ef
--- /dev/null
+++ b/src/designer/src/lib/shared/dialoggui_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/shared/extensionfactory_p.h b/src/designer/src/lib/shared/extensionfactory_p.h
new file mode 100644
index 000000000..3b918c292
--- /dev/null
+++ b/src/designer/src/lib/shared/extensionfactory_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/filterwidget.cpp b/src/designer/src/lib/shared/filterwidget.cpp
new file mode 100644
index 000000000..e6c826cf8
--- /dev/null
+++ b/src/designer/src/lib/shared/filterwidget.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "filterwidget_p.h"
+#include "iconloader_p.h"
+
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QPalette>
+#include <QtGui/QCursor>
+#include <QtGui/QToolButton>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+#include <QtCore/QDebug>
+#include <QtCore/QPropertyAnimation>
+
+enum { debugFilter = 0 };
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+HintLineEdit::HintLineEdit(QWidget *parent) :
+ QLineEdit(parent),
+ m_defaultFocusPolicy(focusPolicy()),
+ m_refuseFocus(false)
+{
+}
+
+IconButton::IconButton(QWidget *parent)
+ : QToolButton(parent)
+{
+ setCursor(Qt::ArrowCursor);
+}
+
+void IconButton::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ // Note isDown should really use the active state but in most styles
+ // this has no proper feedback
+ QIcon::Mode state = QIcon::Disabled;
+ if (isEnabled())
+ state = isDown() ? QIcon::Selected : QIcon::Normal;
+ QPixmap iconpixmap = icon().pixmap(QSize(ICONBUTTON_SIZE, ICONBUTTON_SIZE),
+ state, QIcon::Off);
+ QRect pixmapRect = QRect(0, 0, iconpixmap.width(), iconpixmap.height());
+ pixmapRect.moveCenter(rect().center());
+ painter.setOpacity(m_fader);
+ painter.drawPixmap(pixmapRect, iconpixmap);
+}
+
+void IconButton::animateShow(bool visible)
+{
+ if (visible) {
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+ animation->setDuration(160);
+ animation->setEndValue(1.0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "fader");
+ animation->setDuration(160);
+ animation->setEndValue(0.0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+}
+
+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;
+ }
+ }
+ }
+
+ QLineEdit::focusInEvent(e);
+}
+
+// ------------------- FilterWidget
+FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm) :
+ QWidget(parent),
+ m_editor(new HintLineEdit(this)),
+ m_button(new IconButton(m_editor)),
+ m_buttonwidth(0)
+{
+ m_editor->setPlaceholderText(tr("Filter"));
+
+ // Let the style determine minimum height for our widget
+ QSize size(ICONBUTTON_SIZE + 6, ICONBUTTON_SIZE + 2);
+
+ // Note KDE does not reserve space for the highlight color
+ if (style()->inherits("OxygenStyle")) {
+ size = size.expandedTo(QSize(24, 0));
+ }
+
+ // Make room for clear icon
+ QMargins margins = m_editor->textMargins();
+ if (layoutDirection() == Qt::LeftToRight)
+ margins.setRight(size.width());
+ else
+ margins.setLeft(size.width());
+
+ m_editor->setTextMargins(margins);
+
+ 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);
+
+ // KDE has custom icons for this. Notice that icon namings are counter intuitive
+ // If these icons are not avaiable we use the freedesktop standard name before
+ // falling back to a bundled resource
+ QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ?
+ QLatin1String("edit-clear-locationbar-rtl") :
+ QLatin1String("edit-clear-locationbar-ltr"),
+ QIcon::fromTheme("edit-clear", createIconSet(QLatin1String("cleartext.png"))));
+
+ m_button->setIcon(icon);
+ m_button->setToolTip(tr("Clear text"));
+ 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->text();
+}
+
+void FilterWidget::checkButton(const QString &text)
+{
+ if (m_oldText.isEmpty() || text.isEmpty())
+ m_button->animateShow(!m_editor->text().isEmpty());
+ m_oldText = text;
+}
+
+void FilterWidget::reset()
+{
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO;
+
+ if (!m_editor->text().isEmpty()) {
+ // Editor has lost focus once this is pressed
+ m_editor->clear();
+ emit filterChanged(QString());
+ }
+}
+
+void FilterWidget::resizeEvent(QResizeEvent *)
+{
+ QRect contentRect = m_editor->rect();
+ if (layoutDirection() == Qt::LeftToRight) {
+ const int iconoffset = m_editor->textMargins().right() + 4;
+ m_button->setGeometry(contentRect.adjusted(m_editor->width() - iconoffset, 0, 0, 0));
+ } else {
+ const int iconoffset = m_editor->textMargins().left() + 4;
+ m_button->setGeometry(contentRect.adjusted(0, 0, -m_editor->width() + iconoffset, 0));
+ }
+}
+
+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/src/designer/src/lib/shared/filterwidget_p.h b/src/designer/src/lib/shared/filterwidget_p.h
new file mode 100644
index 000000000..5b5edcd7c
--- /dev/null
+++ b/src/designer/src/lib/shared/filterwidget_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+class QToolButton;
+
+namespace qdesigner_internal {
+
+/* 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). */
+
+#define ICONBUTTON_SIZE 16
+
+class QDESIGNER_SHARED_EXPORT HintLineEdit : public QLineEdit {
+ Q_OBJECT
+public:
+ explicit HintLineEdit(QWidget *parent = 0);
+
+ bool refuseFocus() const;
+ void setRefuseFocus(bool v);
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void focusInEvent(QFocusEvent *e);
+
+private:
+ const Qt::FocusPolicy m_defaultFocusPolicy;
+ bool m_refuseFocus;
+};
+
+// IconButton: This is a simple helper class that represents clickable icons
+
+class IconButton: public QToolButton
+{
+ Q_OBJECT
+ Q_PROPERTY(float fader READ fader WRITE setFader)
+public:
+ IconButton(QWidget *parent);
+ void paintEvent(QPaintEvent *event);
+ float fader() { return m_fader; }
+ void setFader(float value) { m_fader = value; update(); }
+ void animateShow(bool visible);
+
+private:
+ float m_fader;
+};
+
+// 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;
+ void resizeEvent(QResizeEvent *);
+ 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:
+ HintLineEdit *m_editor;
+ IconButton *m_button;
+ int m_buttonwidth;
+ QString m_oldText;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/designer/src/lib/shared/formlayoutmenu.cpp b/src/designer/src/lib/shared/formlayoutmenu.cpp
new file mode 100644
index 000000000..d52bb53f5
--- /dev/null
+++ b/src/designer/src/lib/shared/formlayoutmenu.cpp
@@ -0,0 +1,534 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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, QVariant::fromValue(PropertySheetStringValue(row.labelName)));
+ labelSheet->setChanged(nameIndex, true);
+ formWindow->ensureUniqueObjectName(rc.first);
+ const int textIndex = labelSheet->indexOf(QLatin1String("text"));
+ labelSheet->setProperty(textIndex, QVariant::fromValue(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, QVariant::fromValue(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/src/designer/src/lib/shared/formlayoutmenu_p.h b/src/designer/src/lib/shared/formlayoutmenu_p.h
new file mode 100644
index 000000000..86f8575bd
--- /dev/null
+++ b/src/designer/src/lib/shared/formlayoutmenu_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/shared/formlayoutrowdialog.ui b/src/designer/src/lib/shared/formlayoutrowdialog.ui
new file mode 100644
index 000000000..c0e0cfe2b
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/formwindowbase.cpp b/src/designer/src/lib/shared/formwindowbase.cpp
new file mode 100644
index 000000000..7c87eaf59
--- /dev/null
+++ b/src/designer/src/lib/shared/formwindowbase.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 "qsimpleresource_p.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>
+#include <QtGui/QLabel>
+
+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();
+ const QVariant newValue = sheet->property(index);
+ if (qobject_cast<QLabel *>(sheet->object()) && sheet->propertyName(index) == QLatin1String("text")) {
+ const PropertySheetStringValue newString = qvariant_cast<PropertySheetStringValue>(newValue);
+ // optimize a bit, reset only if the text value might contain a reference to qt resources
+ // (however reloading of icons other than taken from resources might not work here)
+ if (newString.value().contains(QLatin1String(":/"))) {
+ const QVariant resetValue = QVariant::fromValue(PropertySheetStringValue());
+ sheet->setProperty(index, resetValue);
+ }
+ }
+ sheet->setProperty(index, newValue);
+ }
+ 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*)));
+}
+
+QString FormWindowBase::fileContents() const
+{
+ const bool oldValue = QSimpleResource::setWarningsEnabled(false);
+ const QString rc = contents();
+ QSimpleResource::setWarningsEnabled(oldValue);
+ return rc;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/formwindowbase_p.h b/src/designer/src/lib/shared/formwindowbase_p.h
new file mode 100644
index 000000000..f0fb2e204
--- /dev/null
+++ b/src/designer/src/lib/shared/formwindowbase_p.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 contents without warnings. Should be 'contents(bool quiet)'
+ QString fileContents() const;
+
+ // 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/src/designer/src/lib/shared/grid.cpp b/src/designer/src/lib/shared/grid.cpp
new file mode 100644
index 000000000..ba991c782
--- /dev/null
+++ b/src/designer/src/lib/shared/grid.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = qvariant_cast<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)
+{
+ Grid grid;
+ bool anyData = valueFromVariantMap(vm, QLatin1String(KEY_VISIBLE), grid.m_visible);
+ anyData |= valueFromVariantMap(vm, QLatin1String(KEY_SNAPX), grid.m_snapX);
+ anyData |= valueFromVariantMap(vm, QLatin1String(KEY_SNAPY), grid.m_snapY);
+ anyData |= valueFromVariantMap(vm, QLatin1String(KEY_DELTAX), grid.m_deltaX);
+ anyData |= valueFromVariantMap(vm, QLatin1String(KEY_DELTAY), grid.m_deltaY);
+ if (!anyData)
+ return false;
+ if (grid.m_deltaX == 0 || grid.m_deltaY == 0) {
+ qWarning("Attempt to set invalid grid with a spacing of 0.");
+ return false;
+ }
+ *this = grid;
+ return true;
+}
+
+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/src/designer/src/lib/shared/grid_p.h b/src/designer/src/lib/shared/grid_p.h
new file mode 100644
index 000000000..b9c7316df
--- /dev/null
+++ b/src/designer/src/lib/shared/grid_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/gridpanel.cpp b/src/designer/src/lib/shared/gridpanel.cpp
new file mode 100644
index 000000000..0319e5e95
--- /dev/null
+++ b/src/designer/src/lib/shared/gridpanel.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/gridpanel.ui b/src/designer/src/lib/shared/gridpanel.ui
new file mode 100644
index 000000000..adfdd3684
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/gridpanel_p.h b/src/designer/src/lib/shared/gridpanel_p.h
new file mode 100644
index 000000000..adcfa3850
--- /dev/null
+++ b/src/designer/src/lib/shared/gridpanel_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/htmlhighlighter.cpp b/src/designer/src/lib/shared/htmlhighlighter.cpp
new file mode 100644
index 000000000..d16ce62aa
--- /dev/null
+++ b/src/designer/src/lib/shared/htmlhighlighter.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/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/src/designer/src/lib/shared/htmlhighlighter_p.h b/src/designer/src/lib/shared/htmlhighlighter_p.h
new file mode 100644
index 000000000..3c9bfc34b
--- /dev/null
+++ b/src/designer/src/lib/shared/htmlhighlighter_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/iconloader.cpp b/src/designer/src/lib/shared/iconloader.cpp
new file mode 100644
index 000000000..b7f74b224
--- /dev/null
+++ b/src/designer/src/lib/shared/iconloader.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 (const QString &f, candidates) {
+ if (QFile::exists(f))
+ return QIcon(f);
+ }
+
+ return QIcon();
+}
+
+QDESIGNER_SHARED_EXPORT QIcon emptyIcon()
+{
+ return QIcon(QLatin1String(":/trolltech/formeditor/images/emptyicon.png"));
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
diff --git a/src/designer/src/lib/shared/iconloader_p.h b/src/designer/src/lib/shared/iconloader_p.h
new file mode 100644
index 000000000..f0e4d0ace
--- /dev/null
+++ b/src/designer/src/lib/shared/iconloader_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/iconselector.cpp b/src/designer/src/lib/shared/iconselector.cpp
new file mode 100644
index 000000000..0d6e3e0e8
--- /dev/null
+++ b/src/designer/src/lib/shared/iconselector.cpp
@@ -0,0 +1,655 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtGui/QLineEdit>
+#include <QtGui/QLabel>
+#include <QtGui/QValidator>
+#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()
+{
+}
+
+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
+
+static inline QPixmap emptyPixmap()
+{
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ return QPixmap::fromImage(img);
+}
+
+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;
+
+ const 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_emptyIcon(emptyPixmap()),
+ 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") );
+
+ 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()
+{
+}
+
+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();
+}
+
+// --- IconThemeEditor
+
+// Validator for theme line edit, accepts empty or non-blank strings.
+class BlankSuppressingValidator : public QValidator {
+public:
+ explicit BlankSuppressingValidator(QObject * parent = 0) : QValidator(parent) {}
+
+ virtual State validate(QString &input, int &pos) const {
+ const int blankPos = input.indexOf(QLatin1Char(' '));
+ if (blankPos != -1) {
+ pos = blankPos;
+ return Invalid;
+ }
+ return Acceptable;
+ }
+};
+
+struct IconThemeEditorPrivate {
+ IconThemeEditorPrivate();
+
+ const QPixmap m_emptyPixmap;
+ QLineEdit *m_themeLineEdit;
+ QLabel *m_themeLabel;
+};
+
+IconThemeEditorPrivate::IconThemeEditorPrivate() :
+ m_emptyPixmap(emptyPixmap()),
+ m_themeLineEdit(new QLineEdit),
+ m_themeLabel(new QLabel)
+{
+}
+
+IconThemeEditor::IconThemeEditor(QWidget *parent, bool wantResetButton) :
+ QWidget (parent), d(new IconThemeEditorPrivate)
+{
+ QHBoxLayout *mainHLayout = new QHBoxLayout;
+ mainHLayout->setMargin(0);
+
+ // Vertically center theme preview label
+ d->m_themeLabel->setPixmap(d->m_emptyPixmap);
+
+ QVBoxLayout *themeLabelVLayout = new QVBoxLayout;
+ d->m_themeLabel->setMargin(1);
+ themeLabelVLayout->setMargin(0);
+ themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
+ themeLabelVLayout->addWidget(d->m_themeLabel);
+ themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
+ mainHLayout->addLayout(themeLabelVLayout);
+
+ d->m_themeLineEdit = new QLineEdit;
+ d->m_themeLineEdit->setValidator(new BlankSuppressingValidator(d->m_themeLineEdit));
+ connect(d->m_themeLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString)));
+ connect(d->m_themeLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(edited(QString)));
+ mainHLayout->addWidget(d->m_themeLineEdit);
+
+ if (wantResetButton) {
+ QToolButton *themeResetButton = new QToolButton;
+ themeResetButton->setIcon(createIconSet(QLatin1String("resetproperty.png")));
+ connect(themeResetButton, SIGNAL(clicked()), this, SLOT(reset()));
+ mainHLayout->addWidget(themeResetButton);
+ }
+
+ setLayout(mainHLayout);
+ setFocusProxy(d->m_themeLineEdit);
+}
+
+IconThemeEditor::~IconThemeEditor()
+{
+}
+
+void IconThemeEditor::reset()
+{
+ d->m_themeLineEdit->clear();
+ emit edited(QString());
+}
+
+void IconThemeEditor::slotChanged(const QString &theme)
+{
+ updatePreview(theme);
+}
+
+void IconThemeEditor::updatePreview(const QString &t)
+{
+ // Update preview label with icon.
+ if (t.isEmpty() || !QIcon::hasThemeIcon(t)) { // Empty
+ const QPixmap *currentPixmap = d->m_themeLabel->pixmap();
+ if (currentPixmap == 0 || currentPixmap->serialNumber() != d->m_emptyPixmap.serialNumber())
+ d->m_themeLabel->setPixmap(d->m_emptyPixmap);
+ } else {
+ const QIcon icon = QIcon::fromTheme(t);
+ d->m_themeLabel->setPixmap(icon.pixmap(d->m_emptyPixmap.size()));
+ }
+}
+
+QString IconThemeEditor::theme() const
+{
+ return d->m_themeLineEdit->text();
+}
+
+void IconThemeEditor::setTheme(const QString &t)
+{
+ d->m_themeLineEdit->setText(t);
+}
+
+} // qdesigner_internal
+
+QT_END_NAMESPACE
+
+#include "moc_iconselector_p.cpp"
diff --git a/src/designer/src/lib/shared/iconselector_p.h b/src/designer/src/lib/shared/iconselector_p.h
new file mode 100644
index 000000000..4f68b730f
--- /dev/null
+++ b/src/designer/src/lib/shared/iconselector_p.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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>
+
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QtResourceModel;
+class QDesignerFormEditorInterface;
+class QDesignerDialogGuiInterface;
+class QDesignerResourceBrowserInterface;
+
+namespace qdesigner_internal {
+
+class DesignerIconCache;
+class DesignerPixmapCache;
+class PropertySheetIconValue;
+struct IconThemeEditorPrivate;
+
+// Resource Dialog that embeds the language-dependent resource widget as returned by the language extension
+class QDESIGNER_SHARED_EXPORT LanguageResourceDialog : public QDialog
+{
+ Q_OBJECT
+
+ explicit 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:
+ QScopedPointer<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:
+ QScopedPointer<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())
+};
+
+// IconThemeEditor: Let's the user input theme icon names and shows a preview label.
+class QDESIGNER_SHARED_EXPORT IconThemeEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString theme READ theme WRITE setTheme DESIGNABLE true)
+public:
+ explicit IconThemeEditor(QWidget *parent = 0, bool wantResetButton = true);
+ virtual ~IconThemeEditor();
+
+ QString theme() const;
+ void setTheme(const QString &theme);
+
+signals:
+ void edited(const QString &);
+
+public slots:
+ void reset();
+
+private slots:
+ void slotChanged(const QString &);
+
+private:
+ void updatePreview(const QString &);
+
+ QScopedPointer<IconThemeEditorPrivate> d;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ICONSELECTOR_H
+
diff --git a/src/designer/src/lib/shared/invisible_widget.cpp b/src/designer/src/lib/shared/invisible_widget.cpp
new file mode 100644
index 000000000..6aceeaa52
--- /dev/null
+++ b/src/designer/src/lib/shared/invisible_widget.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/invisible_widget_p.h b/src/designer/src/lib/shared/invisible_widget_p.h
new file mode 100644
index 000000000..04ca72458
--- /dev/null
+++ b/src/designer/src/lib/shared/invisible_widget_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/layout.cpp b/src/designer/src/lib/shared/layout.cpp
new file mode 100644
index 000000000..9fe438b08
--- /dev/null
+++ b/src/designer/src/lib/shared/layout.cpp
@@ -0,0 +1,1332 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+ if (!locateWidget(w, row, col, rowspan, colspan))
+ qDebug("ooops, widget '%s' does not fit in layout", w->objectName().toUtf8().constData());
+ const int maxColSpan = col == 0 ? 2 : 1;
+ const int newColSpan = qMin(colspan, maxColSpan);
+ const int newRowSpan = qMin(rowspan, maxRowSpan);
+ if (newColSpan != colspan || newRowSpan != rowspan) {
+ // in case like this:
+ // W1 W1
+ // W1 W2
+ // do:
+ // W1 0
+ // 0 W2
+ for (int i = row; i < row + rowspan - 1; i++)
+ for (int j = col; j < col + colspan - 1; j++)
+ if (i > row + newColSpan - 1 || j > col + newRowSpan - 1)
+ if (cell(i, j) == w)
+ setCell(i, j, 0);
+ 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();
+
+ 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/src/designer/src/lib/shared/layout_p.h b/src/designer/src/lib/shared/layout_p.h
new file mode 100644
index 000000000..f901b63b9
--- /dev/null
+++ b/src/designer/src/lib/shared/layout_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/layoutinfo.cpp b/src/designer/src/lib/shared/layoutinfo.cpp
new file mode 100644
index 000000000..804d069c5
--- /dev/null
+++ b/src/designer/src/lib/shared/layoutinfo.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = parentLayout->findChildren<QLayout*>();
+ 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 = layout->findChild<QLayout*>();
+ 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/src/designer/src/lib/shared/layoutinfo_p.h b/src/designer/src/lib/shared/layoutinfo_p.h
new file mode 100644
index 000000000..dadfa6ff3
--- /dev/null
+++ b/src/designer/src/lib/shared/layoutinfo_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/metadatabase.cpp b/src/designer/src/lib/shared/metadatabase.cpp
new file mode 100644
index 000000000..3cde7da13
--- /dev/null
+++ b/src/designer/src/lib/shared/metadatabase.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/metadatabase_p.h b/src/designer/src/lib/shared/metadatabase_p.h
new file mode 100644
index 000000000..5675217cc
--- /dev/null
+++ b/src/designer/src/lib/shared/metadatabase_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/morphmenu.cpp b/src/designer/src/lib/shared/morphmenu.cpp
new file mode 100644
index 000000000..67121e597
--- /dev/null
+++ b/src/designer/src/lib/shared/morphmenu.cpp
@@ -0,0 +1,635 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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") << QLatin1String("QTextBrowser");
+ 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 = fw->findChildren<QLabel*>();
+ 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 = qvariant_cast<QWidgetList>(parentWidget->property(name));
+ const int index = list.indexOf(oldWidget);
+ if (index != -1) {
+ list.replace(index, newWidget);
+ parentWidget->setProperty(name, QVariant::fromValue(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/src/designer/src/lib/shared/morphmenu_p.h b/src/designer/src/lib/shared/morphmenu_p.h
new file mode 100644
index 000000000..9d20545a6
--- /dev/null
+++ b/src/designer/src/lib/shared/morphmenu_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/newactiondialog.cpp b/src/designer/src/lib/shared/newactiondialog.cpp
new file mode 100644
index 000000000..9aaa347c7
--- /dev/null
+++ b/src/designer/src/lib/shared/newactiondialog.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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.icon.setTheme(m_ui->iconThemeEditor->theme());
+ rc.checkable = m_ui->checkableCheckBox->checkState() == Qt::Checked;
+ rc.keysequence = PropertySheetKeySequenceValue(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.unthemed());
+ m_ui->iconThemeEditor->setTheme(d.icon.theme());
+ m_ui->tooltipEditor->setText(d.toolTip);
+ m_ui->keySequenceEdit->setKeySequence(d.keysequence.value());
+ 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/src/designer/src/lib/shared/newactiondialog.ui b/src/designer/src/lib/shared/newactiondialog.ui
new file mode 100644
index 000000000..aef971058
--- /dev/null
+++ b/src/designer/src/lib/shared/newactiondialog.ui
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::NewActionDialog</class>
+ <widget class="QDialog" name="qdesigner_internal::NewActionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>366</width>
+ <height>270</height>
+ </rect>
+ </property>
+ <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="2" column="0">
+ <widget class="QLabel" name="toolTipLabel">
+ <property name="text">
+ <string>T&amp;oolTip:</string>
+ </property>
+ <property name="buddy">
+ <cstring>tooltipEditor</cstring>
+ </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="3" column="0">
+ <widget class="QLabel" name="iconThemeLabel">
+ <property name="text">
+ <string>Icon th&amp;eme:</string>
+ </property>
+ <property name="buddy">
+ <cstring>iconThemeEditor</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="qdesigner_internal::IconThemeEditor" name="iconThemeEditor" native="true"/>
+ </item>
+ <item row="4" 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="4" 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="1">
+ <widget class="QCheckBox" name="checkableCheckBox">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="checkableLabel">
+ <property name="text">
+ <string>&amp;Checkable:</string>
+ </property>
+ <property name="buddy">
+ <cstring>checkableCheckBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="shortcutLabel">
+ <property name="text">
+ <string>&amp;Shortcut:</string>
+ </property>
+ <property name="buddy">
+ <cstring>keySequenceEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="6" 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>
+ <customwidget>
+ <class>qdesigner_internal::IconThemeEditor</class>
+ <extends>QWidget</extends>
+ <header>iconselector_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/src/designer/src/lib/shared/newactiondialog_p.h b/src/designer/src/lib/shared/newactiondialog_p.h
new file mode 100644
index 000000000..b06d1f9a5
--- /dev/null
+++ b/src/designer/src/lib/shared/newactiondialog_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+ PropertySheetKeySequenceValue 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/src/designer/src/lib/shared/newformwidget.cpp b/src/designer/src/lib/shared/newformwidget.cpp
new file mode 100644
index 000000000..150d97104
--- /dev/null
+++ b/src/designer/src/lib/shared/newformwidget.cpp
@@ -0,0 +1,586 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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::NewFormWidgetFormBuilder
+ 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/src/designer/src/lib/shared/newformwidget.ui b/src/designer/src/lib/shared/newformwidget.ui
new file mode 100644
index 000000000..830057c0e
--- /dev/null
+++ b/src/designer/src/lib/shared/newformwidget.ui
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/lib/shared/newformwidget_p.h b/src/designer/src/lib/shared/newformwidget_p.h
new file mode 100644
index 000000000..940b11ce9
--- /dev/null
+++ b/src/designer/src/lib/shared/newformwidget_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/lib/shared/orderdialog.cpp b/src/designer/src/lib/shared/orderdialog.cpp
new file mode 100644
index 000000000..e992fdd34
--- /dev/null
+++ b/src/designer/src/lib/shared/orderdialog.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/orderdialog.ui b/src/designer/src/lib/shared/orderdialog.ui
new file mode 100644
index 000000000..ae9a73488
--- /dev/null
+++ b/src/designer/src/lib/shared/orderdialog.ui
@@ -0,0 +1,198 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/lib/shared/orderdialog_p.h b/src/designer/src/lib/shared/orderdialog_p.h
new file mode 100644
index 000000000..00d76fb15
--- /dev/null
+++ b/src/designer/src/lib/shared/orderdialog_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#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/src/designer/src/lib/shared/plaintexteditor.cpp b/src/designer/src/lib/shared/plaintexteditor.cpp
new file mode 100644
index 000000000..748cecc41
--- /dev/null
+++ b/src/designer/src/lib/shared/plaintexteditor.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/plaintexteditor_p.h b/src/designer/src/lib/shared/plaintexteditor_p.h
new file mode 100644
index 000000000..830207bbd
--- /dev/null
+++ b/src/designer/src/lib/shared/plaintexteditor_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/plugindialog.cpp b/src/designer/src/lib/shared/plugindialog.cpp
new file mode 100644
index 000000000..9b1212b39
--- /dev/null
+++ b/src/designer/src/lib/shared/plugindialog.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "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(tr("Loaded Plugins"));
+ QFont boldFont = topLevelItem->font(0);
+
+ foreach (const 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(tr("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/src/designer/src/lib/shared/plugindialog.ui b/src/designer/src/lib/shared/plugindialog.ui
new file mode 100644
index 000000000..50d117082
--- /dev/null
+++ b/src/designer/src/lib/shared/plugindialog.ui
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/src/designer/src/lib/shared/plugindialog_p.h b/src/designer/src/lib/shared/plugindialog_p.h
new file mode 100644
index 000000000..0027d6e9f
--- /dev/null
+++ b/src/designer/src/lib/shared/plugindialog_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLUGINDIALOG_H
+#define PLUGINDIALOG_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_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/src/designer/src/lib/shared/pluginmanager.cpp b/src/designer/src/lib/shared/pluginmanager.cpp
new file mode 100644
index 000000000..918fe7d07
--- /dev/null
+++ b/src/designer/src/lib/shared/pluginmanager.cpp
@@ -0,0 +1,786 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 *propertySpecsC = "propertyspecifications";
+static const char *stringPropertySpecC = "stringpropertyspecification";
+static const char *stringPropertyNameAttrC = "name";
+static const char *stringPropertyTypeAttrC = "type";
+static const char *stringPropertyNoTrAttrC = "notr";
+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:
+ // Type of a string property
+ typedef QPair<qdesigner_internal::TextPropertyValidationMode, bool> StringPropertyType;
+ typedef QHash<QString, StringPropertyType> StringPropertyTypeMap;
+
+ explicit QDesignerCustomWidgetSharedData(const QString &thePluginPath) : pluginPath(thePluginPath) {}
+ void clearXML();
+
+ QString pluginPath;
+
+ QString xmlClassName;
+ QString xmlDisplayName;
+ QString xmlLanguage;
+ QString xmlAddPageMethod;
+ QString xmlExtends;
+
+ StringPropertyTypeMap xmlStringPropertyTypeMap;
+};
+
+void QDesignerCustomWidgetSharedData::clearXML()
+{
+ xmlClassName.clear();
+ xmlDisplayName.clear();
+ xmlLanguage.clear();
+ xmlAddPageMethod.clear();
+ xmlExtends.clear();
+ xmlStringPropertyTypeMap.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;
+}
+
+bool QDesignerCustomWidgetData::xmlStringPropertyType(const QString &name, StringPropertyType *type) const
+{
+ QDesignerCustomWidgetSharedData::StringPropertyTypeMap::const_iterator it = m_d->xmlStringPropertyTypeMap.constFind(name);
+ if (it == m_d->xmlStringPropertyTypeMap.constEnd()) {
+ *type = StringPropertyType(qdesigner_internal::ValidationRichText, true);
+ return false;
+ }
+ *type = it.value();
+ return true;
+}
+
+// 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);
+}
+
+static inline QString msgAttributeMissing(const QString &name)
+{
+ return QDesignerPluginManager::tr("A required attribute ('%1') is missing.").arg(name);
+}
+
+static qdesigner_internal::TextPropertyValidationMode typeStringToType(const QString &v, bool *ok)
+{
+ *ok = true;
+ if (v == QLatin1String("multiline"))
+ return qdesigner_internal::ValidationMultiLine;
+ if (v == QLatin1String("richtext"))
+ return qdesigner_internal::ValidationRichText;
+ if (v == QLatin1String("stylesheet"))
+ return qdesigner_internal::ValidationStyleSheet;
+ if (v == QLatin1String("singleline"))
+ return qdesigner_internal::ValidationSingleLine;
+ if (v == QLatin1String("objectname"))
+ return qdesigner_internal::ValidationObjectName;
+ if (v == QLatin1String("objectnamescope"))
+ return qdesigner_internal::ValidationObjectNameScope;
+ if (v == QLatin1String("url"))
+ return qdesigner_internal::ValidationURL;
+ *ok = false;
+ return qdesigner_internal::ValidationRichText;
+}
+
+static bool parsePropertySpecs(QXmlStreamReader &sr,
+ QDesignerCustomWidgetSharedData::StringPropertyTypeMap *rc,
+ QString *errorMessage)
+{
+ const QString propertySpecs = QLatin1String(propertySpecsC);
+ const QString stringPropertySpec = QLatin1String(stringPropertySpecC);
+ const QString stringPropertyTypeAttr = QLatin1String(stringPropertyTypeAttrC);
+ const QString stringPropertyNoTrAttr = QLatin1String(stringPropertyNoTrAttrC);
+ const QString stringPropertyNameAttr = QLatin1String(stringPropertyNameAttrC);
+
+ while (!sr.atEnd()) {
+ switch(sr.readNext()) {
+ case QXmlStreamReader::StartElement: {
+ if (sr.name() != stringPropertySpec) {
+ *errorMessage = QDesignerPluginManager::tr("An invalid property specification ('%1') was encountered. Supported types: %2").arg(sr.name().toString(), stringPropertySpec);
+ return false;
+ }
+ const QXmlStreamAttributes atts = sr.attributes();
+ const QString name = atts.value(stringPropertyNameAttr).toString();
+ const QString type = atts.value(stringPropertyTypeAttr).toString();
+ const QString notrS = atts.value(stringPropertyNoTrAttr).toString(); //Optional
+
+ if (type.isEmpty()) {
+ *errorMessage = msgAttributeMissing(stringPropertyTypeAttr);
+ return false;
+ }
+ if (name.isEmpty()) {
+ *errorMessage = msgAttributeMissing(stringPropertyNameAttr);
+ return false;
+ }
+ bool typeOk;
+ const bool noTr = notrS == QLatin1String("true") || notrS == QLatin1String("1");
+ QDesignerCustomWidgetSharedData::StringPropertyType v(typeStringToType(type, &typeOk), !noTr);
+ if (!typeOk) {
+ *errorMessage = QDesignerPluginManager::tr("'%1' is not a valid string property specification.").arg(type);
+ return false;
+ }
+ rc->insert(name, v);
+ }
+ break;
+ case QXmlStreamReader::EndElement: // Outer </stringproperties>
+ if (sr.name() == propertySpecs)
+ return true;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+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>, <stringproperties>
+ elements.clear();
+ elements.push_back(QLatin1String(extendsElementC));
+ elements.push_back(QLatin1String(addPageMethodC));
+ elements.push_back(QLatin1String(propertySpecsC));
+ 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;
+ case 2: // <stringproperties>
+ if (!parsePropertySpecs(sr, &m_d->xmlStringPropertyTypeMap, errorMessage)) {
+ *errorMessage = msgXmlError(name, *errorMessage);
+ return ParseError;
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+// ---------------- QDesignerPluginManagerPrivate
+
+class QDesignerPluginManagerPrivate {
+ public:
+ typedef QPair<QString, QString> ClassNamePropertyNameKey;
+
+ 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);
+}
+
+QDesignerCustomWidgetData QDesignerPluginManager::customWidgetData(const QString &name) const
+{
+ const int count = m_d->m_customWidgets.size();
+ for (int i = 0; i < count; i++)
+ if (m_d->m_customWidgets.at(i)->name() == name)
+ return m_d->m_customWidgetData.at(i);
+ return QDesignerCustomWidgetData();
+}
+
+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/src/designer/src/lib/shared/pluginmanager_p.h b/src/designer/src/lib/shared/pluginmanager_p.h
new file mode 100644
index 000000000..34aa3041d
--- /dev/null
+++ b/src/designer/src/lib/shared/pluginmanager_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 "shared_enums_p.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QMap>
+#include <QtCore/QPair>
+#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:
+ // StringPropertyType: validation mode and translatable flag.
+ typedef QPair<qdesigner_internal::TextPropertyValidationMode, bool> StringPropertyType;
+
+ 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;
+ // Type of a string property
+ bool xmlStringPropertyType(const QString &name, StringPropertyType *type) 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;
+ QDesignerCustomWidgetData customWidgetData(const QString &className) 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/src/designer/src/lib/shared/previewconfigurationwidget.cpp b/src/designer/src/lib/shared/previewconfigurationwidget.cpp
new file mode 100644
index 000000000..2b4506a37
--- /dev/null
+++ b/src/designer/src/lib/shared/previewconfigurationwidget.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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/TouchScreenPhone.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>
+
+
+static const char *skinResourcePathC = ":/skins/";
+
+QT_BEGIN_NAMESPACE
+
+static const char *skinExtensionC = "skin";
+
+// 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()) {
+ const QString skinPath = QLatin1String(skinResourcePathC);
+ QString pattern = QLatin1String("*.");
+ pattern += QLatin1String(skinExtensionC);
+ const QDir dir(skinPath, pattern);
+ const QFileInfoList list = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot, QDir::Name);
+ 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/src/designer/src/lib/shared/previewconfigurationwidget.ui b/src/designer/src/lib/shared/previewconfigurationwidget.ui
new file mode 100644
index 000000000..2f18766ff
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/previewconfigurationwidget_p.h b/src/designer/src/lib/shared/previewconfigurationwidget_p.h
new file mode 100644
index 000000000..21ea1f197
--- /dev/null
+++ b/src/designer/src/lib/shared/previewconfigurationwidget_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/previewmanager.cpp b/src/designer/src/lib/shared/previewmanager.cpp
new file mode 100644
index 000000000..3857b7864
--- /dev/null
+++ b/src/designer/src/lib/shared/previewmanager.cpp
@@ -0,0 +1,943 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtGui/QMatrix>
+
+#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);
+}
+
+// PreviewDeviceSkin: Forwards the key events to the window and
+// provides context menu with rotation options. Derived class
+// can apply additional transformations to the skin.
+
+class PreviewDeviceSkin : public DeviceSkin
+{
+ Q_OBJECT
+public:
+ enum Direction { DirectionUp, DirectionLeft, DirectionRight };
+
+ 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 *) {}
+
+private slots:
+ void slotDirection(QAction *);
+
+protected:
+ // Fit the widget in case the orientation changes (transposing screensize)
+ virtual void fitWidget(const QSize &size);
+ // Calculate the complete transformation for the skin
+ // (base class implementation provides rotation).
+ virtual QMatrix skinTransform() const;
+
+private:
+ const QSize m_screenSize;
+ Direction m_direction;
+
+ QAction *m_directionUpAction;
+ QAction *m_directionLeftAction;
+ QAction *m_directionRightAction;
+ QAction *m_closeAction;
+};
+
+PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ DeviceSkin(parameters, parent),
+ m_screenSize(parameters.screenSize()),
+ m_direction(DirectionUp),
+ m_directionUpAction(0),
+ m_directionLeftAction(0),
+ m_directionRightAction(0),
+ m_closeAction(0)
+{
+ 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);
+ }
+}
+
+// Create a checkable action with integer data and
+// set it checked if it matches the currentState.
+static inline QAction
+ *createCheckableActionIntData(const QString &label,
+ int actionValue, int currentState,
+ QActionGroup *ag, QObject *parent)
+{
+ QAction *a = new QAction(label, parent);
+ a->setData(actionValue);
+ a->setCheckable(true);
+ if (actionValue == currentState)
+ a->setChecked(true);
+ ag->addAction(a);
+ return a;
+}
+
+void PreviewDeviceSkin::slotPopupMenu()
+{
+ QMenu menu(this);
+ // Create actions
+ if (!m_directionUpAction) {
+ QActionGroup *directionGroup = new QActionGroup(this);
+ connect(directionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotDirection(QAction*)));
+ directionGroup->setExclusive(true);
+ m_directionUpAction = createCheckableActionIntData(tr("&Portrait"), DirectionUp, m_direction, directionGroup, this);
+ //: Rotate form preview counter-clockwise
+ m_directionLeftAction = createCheckableActionIntData(tr("Landscape (&CCW)"), DirectionLeft, m_direction, directionGroup, this);
+ //: Rotate form preview clockwise
+ m_directionRightAction = createCheckableActionIntData(tr("&Landscape (CW)"), DirectionRight, m_direction, directionGroup, this);
+ m_closeAction = new QAction(tr("&Close"), this);
+ connect(m_closeAction, SIGNAL(triggered()), parentWidget(), SLOT(close()));
+ }
+ menu.addAction(m_directionUpAction);
+ menu.addAction(m_directionLeftAction);
+ menu.addAction(m_directionRightAction);
+ menu.addSeparator();
+ populateContextMenu(&menu);
+ menu.addAction(m_closeAction);
+ menu.exec(QCursor::pos());
+}
+
+void PreviewDeviceSkin::slotDirection(QAction *a)
+{
+ const Direction newDirection = static_cast<Direction>(a->data().toInt());
+ if (m_direction == newDirection)
+ return;
+ const Qt::Orientation newOrientation = newDirection == DirectionUp ? Qt::Vertical : Qt::Horizontal;
+ const Qt::Orientation oldOrientation = m_direction == DirectionUp ? Qt::Vertical : Qt::Horizontal;
+ m_direction = newDirection;
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ if (oldOrientation != newOrientation) {
+ QSize size = screenSize();
+ if (newOrientation == Qt::Horizontal)
+ size.transpose();
+ fitWidget(size);
+ }
+ setTransform(skinTransform());
+ QApplication::restoreOverrideCursor();
+}
+
+void PreviewDeviceSkin::fitWidget(const QSize &size)
+{
+ view()->setFixedSize(size);
+}
+
+QMatrix PreviewDeviceSkin::skinTransform() const
+{
+ QMatrix newTransform;
+ switch (m_direction) {
+ case DirectionUp:
+ break;
+ case DirectionLeft:
+ newTransform.rotate(270.0);
+ break;
+ case DirectionRight:
+ newTransform.rotate(90.0);
+ break;
+ }
+ return newTransform;
+}
+
+// ------------ 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);
+ virtual QMatrix skinTransform() const;
+ virtual void fitWidget(const QSize &size);
+
+private:
+ ZoomMenu *m_zoomMenu;
+ QAction *m_zoomSubMenuAction;
+ ZoomWidget *m_zoomWidget;
+};
+
+ZoomablePreviewDeviceSkin::ZoomablePreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ PreviewDeviceSkin(parameters, parent),
+ m_zoomMenu(new ZoomMenu(this)),
+ m_zoomSubMenuAction(0),
+ 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);
+}
+
+static inline qreal zoomFactor(int percent)
+{
+ return qreal(percent) / 100.0;
+}
+
+static inline QSize scaleSize(int zoomPercent, const QSize &size)
+{
+ return zoomPercent == 100 ? size : (QSizeF(size) * zoomFactor(zoomPercent)).toSize();
+}
+
+void ZoomablePreviewDeviceSkin::setPreview(QWidget *formWidget)
+{
+ m_zoomWidget->setWidget(formWidget);
+ m_zoomWidget->resize(scaleSize(zoomPercent(), screenSize()));
+}
+
+int ZoomablePreviewDeviceSkin::zoomPercent() const
+{
+ return m_zoomWidget->zoom();
+}
+
+void ZoomablePreviewDeviceSkin::setZoomPercent(int zp)
+{
+ if (zp == zoomPercent())
+ return;
+
+ // If not triggered by the menu itself: Update it
+ if (m_zoomMenu->zoom() != zp)
+ m_zoomMenu->setZoom(zp);
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_zoomWidget->setZoom(zp);
+ setTransform(skinTransform());
+ QApplication::restoreOverrideCursor();
+}
+
+void ZoomablePreviewDeviceSkin::populateContextMenu(QMenu *menu)
+{
+ if (!m_zoomSubMenuAction) {
+ m_zoomSubMenuAction = new QAction(tr("&Zoom"), this);
+ QMenu *zoomSubMenu = new QMenu;
+ m_zoomSubMenuAction->setMenu(zoomSubMenu);
+ m_zoomMenu->addActions(zoomSubMenu);
+ }
+ menu->addAction(m_zoomSubMenuAction);
+ menu->addSeparator();
+}
+
+QMatrix ZoomablePreviewDeviceSkin::skinTransform() const
+{
+ // Complete transformation consisting of base class rotation and zoom.
+ QMatrix rc = PreviewDeviceSkin::skinTransform();
+ const int zp = zoomPercent();
+ if (zp != 100) {
+ const qreal factor = zoomFactor(zp);
+ rc.scale(factor, factor);
+ }
+ return rc;
+}
+
+void ZoomablePreviewDeviceSkin::fitWidget(const QSize &size)
+{
+ m_zoomWidget->resize(scaleSize(zoomPercent(), size));
+}
+
+// ------------- 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);
+ formWidget->setWindowTitle(title);
+
+ // 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/src/designer/src/lib/shared/previewmanager_p.h b/src/designer/src/lib/shared/previewmanager_p.h
new file mode 100644
index 000000000..3ca8619ce
--- /dev/null
+++ b/src/designer/src/lib/shared/previewmanager_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/promotionmodel.cpp b/src/designer/src/lib/shared/promotionmodel.cpp
new file mode 100644
index 000000000..deab66fa1
--- /dev/null
+++ b/src/designer/src/lib/shared/promotionmodel.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/promotionmodel_p.h b/src/designer/src/lib/shared/promotionmodel_p.h
new file mode 100644
index 000000000..214efb135
--- /dev/null
+++ b/src/designer/src/lib/shared/promotionmodel_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/promotiontaskmenu.cpp b/src/designer/src/lib/shared/promotiontaskmenu.cpp
new file mode 100644
index 000000000..dc76ef6cf
--- /dev/null
+++ b/src/designer/src/lib/shared/promotiontaskmenu.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/promotiontaskmenu_p.h b/src/designer/src/lib/shared/promotiontaskmenu_p.h
new file mode 100644
index 000000000..94bf78729
--- /dev/null
+++ b/src/designer/src/lib/shared/promotiontaskmenu_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/propertylineedit.cpp b/src/designer/src/lib/shared/propertylineedit.cpp
new file mode 100644
index 000000000..29dff63ab
--- /dev/null
+++ b/src/designer/src/lib/shared/propertylineedit.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/propertylineedit_p.h b/src/designer/src/lib/shared/propertylineedit_p.h
new file mode 100644
index 000000000..b968b18bf
--- /dev/null
+++ b/src/designer/src/lib/shared/propertylineedit_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_command.cpp b/src/designer/src/lib/shared/qdesigner_command.cpp
new file mode 100644
index 000000000..f4e250d89
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_command.cpp
@@ -0,0 +1,2968 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = qvariant_cast<QWidgetList>(parentWidget->property(name));
+ list.removeAll(widget);
+ if (index >= 0 && index < list.size()) {
+ list.insert(index, widget);
+ } else {
+ list.append(widget);
+ }
+ parentWidget->setProperty(name, QVariant::fromValue(list));
+}
+
+static int removeFromWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name)
+{
+ QWidgetList list = qvariant_cast<QWidgetList>(parentWidget->property(name));
+ const int firstIndex = list.indexOf(widget);
+ if (firstIndex != -1) {
+ list.removeAll(widget);
+ parentWidget->setProperty(name, QVariant::fromValue(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 = formWindow()->findChildren<QLabel*>();
+ 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 = qvariant_cast<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", QVariant::fromValue(reorderWidget(m_oldParentZOrder, m_widget)));
+
+ reorder(m_widget);
+}
+
+void ChangeZOrderCommand::undo()
+{
+ m_widget->parentWidget()->setProperty("_q_zOrder", QVariant::fromValue(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 = m_widget->findChildren<QWidget *>();
+ 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 = qvariant_cast<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder"));
+ m_oldParentZOrder = qvariant_cast<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", QVariant::fromValue(oldList));
+
+ QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder"));
+ newList.append(m_widget);
+ m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList));
+
+ QWidgetList oldZOrder = m_oldParentZOrder;
+ oldZOrder.removeAll(m_widget);
+ m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(oldZOrder));
+
+ QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder"));
+ newZOrder.append(m_widget);
+ m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(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", QVariant::fromValue(m_oldParentList));
+
+ QWidgetList newList = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_widgetOrder"));
+ newList.removeAll(m_widget);
+ m_newParentWidget->setProperty("_q_widgetOrder", QVariant::fromValue(newList));
+
+ m_oldParentWidget->setProperty("_q_zOrder", QVariant::fromValue(m_oldParentZOrder));
+
+ QWidgetList newZOrder = qvariant_cast<QWidgetList>(m_newParentWidget->property("_q_zOrder"));
+ m_newParentWidget->setProperty("_q_zOrder", QVariant::fromValue(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")), QVariant::fromValue(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(QLatin1String("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")), QVariant::fromValue(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(QLatin1String("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(QLatin1String("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(QLatin1String("page"));
+ break;
+ case MdiContainer:
+ setText(QApplication::translate("Command", "Insert Subwindow"));
+ m_widget = new QDesignerWidget(formWindow(), m_containerWidget);
+ m_widget->setObjectName(QLatin1String("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, QVariant::fromValue((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(qvariant_cast<PropertySheetIconValue>(it.value())));
+ break;
+ case Qt::DisplayPropertyRole:
+ item->setText(qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::ToolTipPropertyRole:
+ item->setToolTip(qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::StatusTipPropertyRole:
+ item->setStatusTip(qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::WhatsThisPropertyRole:
+ item->setWhatsThis(qvariant_cast<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, QVariant::fromValue(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(qvariant_cast<PropertySheetIconValue>(it.value())));
+ break;
+ case Qt::DisplayPropertyRole:
+ item->setText(column, qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::ToolTipPropertyRole:
+ item->setToolTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::StatusTipPropertyRole:
+ item->setStatusTip(column, qvariant_cast<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::WhatsThisPropertyRole:
+ item->setWhatsThis(column, qvariant_cast<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(qvariant_cast<PropertySheetIconValue>(
+ hash.m_properties[Qt::DecorationPropertyRole]));
+ QVariant var = hash.m_properties[Qt::DisplayPropertyRole];
+ PropertySheetStringValue str = qvariant_cast<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 = qvariant_cast<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, QVariant::fromValue(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/src/designer/src/lib/shared/qdesigner_command2.cpp b/src/designer/src/lib/shared/qdesigner_command2.cpp
new file mode 100644
index 000000000..2b0a5a21a
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_command2.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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);
+}
+
+LayoutAlignmentCommand::LayoutAlignmentCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Change layout alignment"), formWindow),
+ m_newAlignment(0), m_oldAlignment(0), m_widget(0)
+{
+}
+
+bool LayoutAlignmentCommand::init(QWidget *w, Qt::Alignment alignment)
+{
+ bool enabled;
+ m_newAlignment = alignment;
+ m_oldAlignment = LayoutAlignmentCommand::alignmentOf(core(), w, &enabled);
+ m_widget = w;
+ return enabled;
+}
+
+void LayoutAlignmentCommand::redo()
+{
+ LayoutAlignmentCommand::applyAlignment(core(), m_widget, m_newAlignment);
+}
+
+void LayoutAlignmentCommand::undo()
+{
+ LayoutAlignmentCommand::applyAlignment(core(), m_widget, m_oldAlignment);
+}
+
+// Find out alignment and return whether command is enabled.
+Qt::Alignment LayoutAlignmentCommand::alignmentOf(const QDesignerFormEditorInterface *core, QWidget *w, bool *enabledIn)
+{
+ bool managed;
+ QLayout *layout;
+
+ if (enabledIn)
+ *enabledIn = false;
+ // Can only work on a managed layout
+ const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core, w, &managed, &layout);
+ const bool enabled = layout && managed &&
+ (type == LayoutInfo::HBox || type == LayoutInfo::VBox
+ || type == LayoutInfo::Grid);
+ if (!enabled)
+ return Qt::Alignment(0);
+ // Get alignment
+ const int index = layout->indexOf(w);
+ Q_ASSERT(index >= 0);
+ if (enabledIn)
+ *enabledIn = true;
+ return layout->itemAt(index)->alignment();
+}
+
+void LayoutAlignmentCommand::applyAlignment(const QDesignerFormEditorInterface *core, QWidget *w, Qt::Alignment a)
+{
+ // Find layout and apply to item
+ QLayout *layout;
+ LayoutInfo::laidoutWidgetType(core, w, 0, &layout);
+ if (layout) {
+ const int index = layout->indexOf(w);
+ if (index >= 0) {
+ layout->itemAt(index)->setAlignment(a);
+ layout->update();
+ }
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/qdesigner_command2_p.h b/src/designer/src/lib/shared/qdesigner_command2_p.h
new file mode 100644
index 000000000..0a6cce88e
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_command2_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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;
+};
+
+// Change the alignment of a widget in a managed grid/box layout cell.
+class LayoutAlignmentCommand : public QDesignerFormWindowCommand {
+ Q_DISABLE_COPY(LayoutAlignmentCommand)
+public:
+ explicit LayoutAlignmentCommand(QDesignerFormWindowInterface *formWindow);
+
+ bool init(QWidget *w, Qt::Alignment alignment);
+
+ virtual void redo();
+ virtual void undo();
+
+ // Find out alignment and return whether command is enabled.
+ static Qt::Alignment alignmentOf(const QDesignerFormEditorInterface *core, QWidget *w, bool *enabled = 0);
+
+private:
+ static void applyAlignment(const QDesignerFormEditorInterface *core, QWidget *w, Qt::Alignment a);
+
+ Qt::Alignment m_newAlignment;
+ Qt::Alignment m_oldAlignment;
+ QWidget *m_widget;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_COMMAND2_H
diff --git a/src/designer/src/lib/shared/qdesigner_command_p.h b/src/designer/src/lib/shared/qdesigner_command_p.h
new file mode 100644
index 000000000..323cec5e5
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_command_p.h
@@ -0,0 +1,1136 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_dnditem.cpp b/src/designer/src/lib/shared/qdesigner_dnditem.cpp
new file mode 100644
index 000000000..83218026a
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_dnditem.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_dnditem_p.h b/src/designer/src/lib/shared/qdesigner_dnditem_p.h
new file mode 100644
index 000000000..8c9d2e672
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_dnditem_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_dockwidget.cpp b/src/designer/src/lib/shared/qdesigner_dockwidget.cpp
new file mode 100644
index 000000000..8aad4579c
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_dockwidget.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_dockwidget_p.h b/src/designer/src/lib/shared/qdesigner_dockwidget_p.h
new file mode 100644
index 000000000..106ed1fb6
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_dockwidget_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_formbuilder.cpp b/src/designer/src/lib/shared/qdesigner_formbuilder.cpp
new file mode 100644
index 000000000..a8054748b
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formbuilder.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+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;
+}
+#endif
+
+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);
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ // 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);
+#endif
+}
+
+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 (sheetValue.canConvert<PropertySheetFlagValue>()) {
+ 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 (sheetValue.canConvert<PropertySheetEnumValue>()) {
+ 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);
+ }
+ }
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ // Check for script errors
+ *scriptErrors = builder.formScriptRunner()->errors();
+ if (!scriptErrors->empty()) {
+ *errorMessage = summarizeScriptErrors(*scriptErrors);
+ delete widget;
+ return 0;
+ }
+#endif
+ // 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;
+}
+
+// ---------- NewFormWidgetFormBuilder
+
+NewFormWidgetFormBuilder::NewFormWidgetFormBuilder(QDesignerFormEditorInterface *core,
+ Mode mode,
+ const DeviceProfile &deviceProfile) :
+ QDesignerFormBuilder(core, mode, deviceProfile)
+{
+}
+
+void NewFormWidgetFormBuilder::createCustomWidgets(DomCustomWidgets *dc)
+{
+ QSimpleResource::handleDomCustomWidgets(core(), dc);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/qdesigner_formbuilder_p.h b/src/designer/src/lib/shared/qdesigner_formbuilder_p.h
new file mode 100644
index 000000000..2f902e394
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formbuilder_p.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 and widget box.
+ * 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;
+};
+
+// Form builder for a new form widget (preview). To allow for promoted
+// widgets in the template, it implements the handling of custom widgets
+// (adding of them to the widget database).
+
+class QDESIGNER_SHARED_EXPORT NewFormWidgetFormBuilder: public QDesignerFormBuilder {
+public:
+ NewFormWidgetFormBuilder(QDesignerFormEditorInterface *core,
+ Mode mode,
+ const DeviceProfile &deviceProfile = DeviceProfile());
+
+protected:
+ virtual void createCustomWidgets(DomCustomWidgets *);
+};
+
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMBUILDER_H
diff --git a/src/designer/src/lib/shared/qdesigner_formeditorcommand.cpp b/src/designer/src/lib/shared/qdesigner_formeditorcommand.cpp
new file mode 100644
index 000000000..bff14ac5b
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formeditorcommand.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "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/src/designer/src/lib/shared/qdesigner_formeditorcommand_p.h b/src/designer/src/lib/shared/qdesigner_formeditorcommand_p.h
new file mode 100644
index 000000000..7b88be9e6
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formeditorcommand_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_formwindowcommand.cpp b/src/designer/src/lib/shared/qdesigner_formwindowcommand.cpp
new file mode 100644
index 000000000..3efc82994
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formwindowcommand.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "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 *parent)
+ : QUndoCommand(description, parent),
+ 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 = form->findChildren<QLabel*>();
+ 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/src/designer/src/lib/shared/qdesigner_formwindowcommand_p.h b/src/designer/src/lib/shared/qdesigner_formwindowcommand_p.h
new file mode 100644
index 000000000..7c98559e3
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formwindowcommand_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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,
+ QUndoCommand *parent = 0);
+
+ 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/src/designer/src/lib/shared/qdesigner_formwindowmanager.cpp b/src/designer/src/lib/shared/qdesigner_formwindowmanager.cpp
new file mode 100644
index 000000000..1521e146e
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formwindowmanager.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_formwindowmanager_p.h b/src/designer/src/lib/shared/qdesigner_formwindowmanager_p.h
new file mode 100644
index 000000000..43c9149fc
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_formwindowmanager_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_integration.cpp b/src/designer/src/lib/shared/qdesigner_integration.cpp
new file mode 100644
index 000000000..7470bbf80
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_integration.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_integration_p.h b/src/designer/src/lib/shared/qdesigner_integration_p.h
new file mode 100644
index 000000000..f4fdff7db
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_integration_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_introspection.cpp b/src/designer/src/lib/shared/qdesigner_introspection.cpp
new file mode 100644
index 000000000..9d45acca6
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_introspection.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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();
+ 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/src/designer/src/lib/shared/qdesigner_introspection_p.h b/src/designer/src/lib/shared/qdesigner_introspection_p.h
new file mode 100644
index 000000000..ed4785f87
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_introspection_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_membersheet.cpp b/src/designer/src/lib/shared/qdesigner_membersheet.cpp
new file mode 100644
index 000000000..f70fc389b
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_membersheet.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_membersheet_p.h b/src/designer/src/lib/shared/qdesigner_membersheet_p.h
new file mode 100644
index 000000000..0f0f5736c
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_membersheet_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_menu.cpp b/src/designer/src/lib/shared/qdesigner_menu.cpp
new file mode 100644
index 000000000..e9abf30cd
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_menu.cpp
@@ -0,0 +1,1390 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+
+// give the user a little more space to click on the sub menu rectangle
+static inline void extendClickableArea(QRect *subMenuRect, Qt::LayoutDirection dir)
+{
+ switch (dir) {
+ case Qt::LayoutDirectionAuto: // Should never happen
+ case Qt::LeftToRight:
+ subMenuRect->setLeft(subMenuRect->left() - 20);
+ break;
+ case Qt::RightToLeft:
+ subMenuRect->setRight(subMenuRect->right() + 20);
+ break;
+ }
+}
+
+QDesignerMenu::QDesignerMenu(QWidget *parent) :
+ QMenu(parent),
+ m_subMenuPixmap(QPixmap(QLatin1String(":/trolltech/formeditor/images/submenu.png"))),
+ 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);
+ extendClickableArea(&pm_rect, layoutDirection());
+ }
+
+ 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);
+ extendClickableArea(&pm_rect, layoutDirection());
+
+ 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;
+ itemData.setValue(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
+{
+ const QRect g = actionGeometry(action);
+ const int x = layoutDirection() == Qt::LeftToRight ? (g.right() - m_subMenuPixmap.width() - 2) : 2;
+ const int y = g.top() + (g.height() - m_subMenuPixmap.height())/2 + 1;
+ return QRect(x, y, m_subMenuPixmap.width(), m_subMenuPixmap.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)) {
+ p.drawPixmap(subMenuPixmapRect(a).topLeft(), m_subMenuPixmap);
+ }
+ }
+
+ 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 += findChildren<QDesignerMenu*>();
+
+ 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, w->findChildren<QMenu*>()) {
+ subMenu->hide();
+ }
+ }
+
+ m_lastSubMenuIndex = -1;
+}
+
+// Close submenu using the left/right keys according to layoutDirection().
+// Return false to indicate the event must be propagated to the menu bar.
+bool QDesignerMenu::hideSubMenuOnCursorKey()
+{
+ if (parentMenu()) {
+ hide();
+ return true;
+ }
+ closeMenuChain();
+ update();
+ if (parentMenuBar())
+ return false;
+ return true;
+}
+
+// Open a submenu using the left/right keys according to layoutDirection().
+// Return false to indicate the event must be propagated to the menu bar.
+bool QDesignerMenu::showSubMenuOnCursorKey()
+{
+ const QAction *action = currentAction();
+
+ if (qobject_cast<const SpecialMenuAction*>(action) || action->isSeparator()) {
+ closeMenuChain();
+ if (parentMenuBar())
+ return false;
+ return true;
+ }
+ m_lastSubMenuIndex = -1; // force a refresh
+ slotShowSubMenuNow();
+ return true;
+}
+
+void QDesignerMenu::moveLeft()
+{
+ const bool handled = layoutDirection() == Qt::LeftToRight ?
+ hideSubMenuOnCursorKey() : showSubMenuOnCursorKey();
+ if (!handled)
+ parentMenuBar()->moveLeft();
+}
+
+void QDesignerMenu::moveRight()
+{
+ const bool handled = layoutDirection() == Qt::LeftToRight ?
+ showSubMenuOnCursorKey() : hideSubMenuOnCursorKey();
+ if (!handled)
+ parentMenuBar()->moveRight();
+}
+
+void QDesignerMenu::moveUp(bool ctrl)
+{
+ if (m_currentIndex == 0) {
+ hide();
+ return;
+ }
+
+ if (ctrl)
+ (void) swap(m_currentIndex, m_currentIndex - 1);
+ --m_currentIndex;
+ 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;
+ 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);
+ if (layoutDirection() == Qt::LeftToRight) {
+ menu->move(mapToGlobal(g.topRight()));
+ } else {
+ // The position is not initially correct due to the unknown width,
+ // causing it to overlap a bit the first time it is invoked.
+ const QSize menuSize = menu->size();
+ QPoint point = g.topLeft() - QPoint(menu->width() + 10, 0);
+ menu->move(mapToGlobal(point));
+ }
+ 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, findChildren<QMenu*>()) {
+ 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/src/designer/src/lib/shared/qdesigner_menu_p.h b/src/designer/src/lib/shared/qdesigner_menu_p.h
new file mode 100644
index 000000000..b88af7aac
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_menu_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 <QtGui/QPixmap>
+#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:
+ bool hideSubMenuOnCursorKey();
+ bool showSubMenuOnCursorKey();
+ const QPixmap m_subMenuPixmap;
+
+ 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/src/designer/src/lib/shared/qdesigner_menubar.cpp b/src/designer/src/lib/shared/qdesigner_menubar.cpp
new file mode 100644
index 000000000..534cf0cda
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_menubar.cpp
@@ -0,0 +1,979 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+ // Fake property: Keep the menu bar editable in the form even if a native menu bar is used.
+ setNativeMenuBar(false);
+
+ 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();
+ moveLeft(e->modifiers() & Qt::ControlModifier);
+ return true;
+
+ case Qt::Key_Right:
+ e->accept();
+ moveRight(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;
+ itemData.setValue(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
+}
+
+bool QDesignerMenuBar::dragging() const
+{
+ return m_dragging;
+}
+
+void QDesignerMenuBar::moveLeft(bool ctrl)
+{
+ if (layoutDirection() == Qt::LeftToRight) {
+ movePrevious(ctrl);
+ } else {
+ moveNext(ctrl);
+ }
+}
+
+void QDesignerMenuBar::moveRight(bool ctrl)
+{
+ if (layoutDirection() == Qt::LeftToRight) {
+ moveNext(ctrl);
+ } else {
+ movePrevious(ctrl);
+ }
+}
+
+void QDesignerMenuBar::movePrevious(bool ctrl)
+{
+ const bool swapped = ctrl && swapActions(m_currentIndex, m_currentIndex - 1);
+ const int newIndex = qMax(0, m_currentIndex - 1);
+ // Always re-select, swapping destroys order
+ if (swapped || newIndex != m_currentIndex) {
+ m_currentIndex = newIndex;
+ updateCurrentAction(true);
+ }
+}
+
+void QDesignerMenuBar::moveNext(bool ctrl)
+{
+ const bool swapped = ctrl && swapActions(m_currentIndex + 1, m_currentIndex);
+ const int newIndex = qMin(actions().count() - 1, m_currentIndex + 1);
+ if (swapped || newIndex != m_currentIndex) {
+ m_currentIndex = newIndex;
+ 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();
+ if (layoutDirection() == Qt::LeftToRight) {
+ menu->move(mapToGlobal(g.bottomLeft()));
+ } else {
+ // The position is not initially correct due to the unknown width,
+ // causing it to overlap a bit the first time it is invoked.
+ const QSize menuSize = menu->size();
+ QPoint point = g.bottomRight() - QPoint(menu->width(), 0);
+ menu->move(mapToGlobal(point));
+ }
+ 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::swapActions(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/src/designer/src/lib/shared/qdesigner_menubar_p.h b/src/designer/src/lib/shared/qdesigner_menubar_p.h
new file mode 100644
index 000000000..8ca538559
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_menubar_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 swapActions(int a, int b);
+
+private:
+ void updateCurrentAction(bool selectAction);
+ void movePrevious(bool ctrl);
+ void moveNext(bool ctrl);
+
+ 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/src/designer/src/lib/shared/qdesigner_objectinspector.cpp b/src/designer/src/lib/shared/qdesigner_objectinspector.cpp
new file mode 100644
index 000000000..314638c74
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_objectinspector.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_objectinspector_p.h b/src/designer/src/lib/shared/qdesigner_objectinspector_p.h
new file mode 100644
index 000000000..9cc630ef6
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_objectinspector_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit 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/src/designer/src/lib/shared/qdesigner_promotion.cpp b/src/designer/src/lib/shared/qdesigner_promotion.cpp
new file mode 100644
index 000000000..bf96b473b
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_promotion.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_promotion_p.h b/src/designer/src/lib/shared/qdesigner_promotion_p.h
new file mode 100644
index 000000000..b1af1db93
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_promotion_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_promotiondialog.cpp b/src/designer/src/lib/shared/qdesigner_promotiondialog.cpp
new file mode 100644
index 000000000..6463016b1
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_promotiondialog.cpp
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtDesigner/QDesignerIntegrationInterface>
+#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()) {
+ const QChar dot(QLatin1Char('.'));
+ QString suggestedHeader = m_promotedHeaderLowerCase ?
+ className.toLower() : className;
+ suggestedHeader.replace(QLatin1String("::"), QString(QLatin1Char('_')));
+ if (!m_promotedHeaderSuffix.startsWith(dot))
+ suggestedHeader += dot;
+ suggestedHeader += m_promotedHeaderSuffix;
+
+ 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);
+ newPromotedClassPanel->setPromotedHeaderSuffix(core->integration()->headerSuffix());
+ newPromotedClassPanel->setPromotedHeaderLowerCase(core->integration()->isHeaderLowercase());
+ 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/src/designer/src/lib/shared/qdesigner_promotiondialog_p.h b/src/designer/src/lib/shared/qdesigner_promotiondialog_p.h
new file mode 100644
index 000000000..73cf7ad50
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_promotiondialog_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit NewPromotedClassPanel(const QStringList &baseClasses,
+ int selectedBaseClass = -1,
+ QWidget *parent = 0);
+
+ QString promotedHeaderSuffix() const { return m_promotedHeaderSuffix; }
+ void setPromotedHeaderSuffix(const QString &s) { m_promotedHeaderSuffix = s; }
+
+ bool isPromotedHeaderLowerCase() const { return m_promotedHeaderLowerCase; }
+ void setPromotedHeaderLowerCase(bool l) { m_promotedHeaderLowerCase = l; }
+
+ 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();
+
+ QString m_promotedHeaderSuffix;
+ bool m_promotedHeaderLowerCase;
+
+ 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 };
+
+ explicit 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/src/designer/src/lib/shared/qdesigner_propertycommand.cpp b/src/designer/src/lib/shared/qdesigner_propertycommand.cpp
new file mode 100644
index 000000000..a9949d85c
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertycommand.cpp
@@ -0,0 +1,1503 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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)
+{
+ // Do not clobber new value in the comparison function in
+ // case someone sets a QString on a PropertySheetStringValue.
+ if (q1.type() != q2.type())
+ return SubPropertyAll;
+ 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(QVariant::fromValue(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(QVariant::fromValue(font), font.resolve());
+ }
+ case QVariant::Palette: {
+ QPalette palette = applyPaletteSubProperty(qvariant_cast<QPalette>(oldValue), qvariant_cast<QPalette>(newValue), mask);
+ return PropertyHelper::Value(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(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(QVariant::fromValue(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;
+ v.setValue(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());
+ value.setValue(size);
+ }
+
+ break;
+ case SP_MaximumSize: {
+ QSize fs, cs;
+ checkSizes(fw, value.toSize(), &fs, &cs);
+ container->setMaximumSize(cs);
+ fw->mainContainer()->setMaximumSize(fs);
+ value.setValue(fs);
+
+ }
+ break;
+ case SP_Geometry: {
+ QRect r = value.toRect();
+ QSize fs, cs;
+ checkSizes(fw, r.size(), &fs, &cs);
+ container->resize(cs);
+ r.setSize(fs);
+ value.setValue(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 = qvariant_cast<PropertySheetStringValue>(oldValue).value();
+ const QString newName = qvariant_cast<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 = qvariant_cast<PropertySheetStringValue>(oldValue).value();
+ const QString newName = qvariant_cast<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,
+ QUndoCommand *parent) :
+ QDesignerFormWindowCommand(QString(), formWindow, parent)
+{
+}
+
+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;
+ }
+
+ const PropertyHelperPtr ph(createPropertyHelper(object, m_propertyDescription.m_specialProperty, sheet, index));
+ m_propertyHelperList.push_back(ph);
+ return true;
+}
+
+PropertyHelper *PropertyListCommand::createPropertyHelper(QObject *object, SpecialProperty sp,
+ QDesignerPropertySheetExtension *sheet, int sheetIndex) const
+{
+ return new PropertyHelper(object, sp, sheet, sheetIndex);
+}
+
+// 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.at(index)->object();
+}
+
+QVariant PropertyListCommand::oldValue(int index) const
+{
+ Q_ASSERT(index < m_propertyHelperList.size());
+ return m_propertyHelperList.at(index)->oldValue();
+}
+
+void PropertyListCommand::setOldValue(const QVariant &oldValue, int index)
+{
+ Q_ASSERT(index < m_propertyHelperList.size());
+ m_propertyHelperList.at(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) {
+ PropertyHelper *ph = it->data();
+ if (QObject* object = ph->object()) { // Might have been deleted in the meantime
+ const PropertyHelper::Value newValue = function( *ph );
+ updateMask |= ph->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.at(i)->canMerge(*other.at(i)))
+ return false;
+ }
+ return true;
+}
+
+// ---- SetPropertyCommand ----
+SetPropertyCommand::SetPropertyCommand(QDesignerFormWindowInterface *formWindow,
+ QUndoCommand *parent)
+ : PropertyListCommand(formWindow, parent),
+ 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().at(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;
+}
+
+QVariant SetPropertyCommand::mergeValue(const QVariant &newValue)
+{
+ return newValue;
+}
+
+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;
+
+ const QVariant newValue = mergeValue(cmd->newValue());
+ if (!newValue.isValid())
+ return false;
+ m_newValue = 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().at(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/src/designer/src/lib/shared/qdesigner_propertycommand_p.h b/src/designer/src/lib/shared/qdesigner_propertycommand_p.h
new file mode 100644
index 000000000..0dc1825fe
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertycommand_p.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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>
+#include <QtCore/QSharedPointer>
+
+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 QDESIGNER_SHARED_EXPORT PropertyHelper {
+ Q_DISABLE_COPY(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);
+ virtual ~PropertyHelper() {}
+
+ QObject *object() const { return m_object; }
+ SpecialProperty specialProperty() const { return m_specialProperty; }
+ // set a new value. Can be overwritten to perform a transformation (see
+ // handling of Arrow key move in FormWindow class).
+ virtual 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, QUndoCommand *parent = 0);
+
+ 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 QSharedPointer<PropertyHelper> PropertyHelperPtr;
+ typedef QList<PropertyHelperPtr> 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; }
+
+protected:
+ virtual PropertyHelper *createPropertyHelper(QObject *o, SpecialProperty sp,
+ QDesignerPropertySheetExtension *sheet, int sheetIndex) const;
+
+private:
+ PropertyDescription m_propertyDescription;
+ PropertyHelperList m_propertyHelperList;
+};
+
+class QDESIGNER_SHARED_EXPORT SetPropertyCommand: public PropertyListCommand
+{
+
+public:
+ typedef QList<QObject *> ObjectList;
+
+ explicit SetPropertyCommand(QDesignerFormWindowInterface *formWindow, QUndoCommand *parent = 0);
+
+ 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();
+
+protected:
+ virtual QVariant mergeValue(const QVariant &newValue);
+
+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/src/designer/src/lib/shared/qdesigner_propertyeditor.cpp b/src/designer/src/lib/shared/qdesigner_propertyeditor.cpp
new file mode 100644
index 000000000..e3a92e289
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertyeditor.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_propertyeditor_p.h"
+#include "pluginmanager_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <widgetfactory_p.h>
+#include <QtGui/QAction>
+#include <QtGui/QLineEdit>
+#include <QtGui/QAbstractButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+typedef QDesignerPropertyEditor::StringPropertyParameters StringPropertyParameters;
+// A map of property name to type
+typedef QHash<QString, StringPropertyParameters> PropertyNameTypeMap;
+
+// Compile a map of hard-coded string property types
+static const PropertyNameTypeMap &stringPropertyTypes()
+{
+ static PropertyNameTypeMap propertyNameTypeMap;
+ if (propertyNameTypeMap.empty()) {
+ const StringPropertyParameters richtext(ValidationRichText, true);
+ // Accessibility. Both are texts the narrator reads
+ propertyNameTypeMap.insert(QLatin1String("accessibleDescription"), richtext);
+ propertyNameTypeMap.insert(QLatin1String("accessibleName"), richtext);
+ // object names
+ const StringPropertyParameters objectName(ValidationObjectName, false);
+ propertyNameTypeMap.insert(QLatin1String("buddy"), objectName);
+ propertyNameTypeMap.insert(QLatin1String("currentItemName"), objectName);
+ propertyNameTypeMap.insert(QLatin1String("currentPageName"), objectName);
+ propertyNameTypeMap.insert(QLatin1String("currentTabName"), objectName);
+ propertyNameTypeMap.insert(QLatin1String("layoutName"), objectName);
+ propertyNameTypeMap.insert(QLatin1String("spacerName"), objectName);
+ // Style sheet
+ propertyNameTypeMap.insert(QLatin1String("styleSheet"), StringPropertyParameters(ValidationStyleSheet, false));
+ // Buttons/ QCommandLinkButton
+ const StringPropertyParameters multiline(ValidationMultiLine, true);
+ propertyNameTypeMap.insert(QLatin1String("description"), multiline);
+ propertyNameTypeMap.insert(QLatin1String("iconText"), multiline);
+ // Tooltips, etc.
+ propertyNameTypeMap.insert(QLatin1String("toolTip"), richtext);
+ propertyNameTypeMap.insert(QLatin1String("whatsThis"), richtext);
+ propertyNameTypeMap.insert(QLatin1String("windowIconText"), richtext);
+ propertyNameTypeMap.insert(QLatin1String("html"), richtext);
+ // A QWizard page id
+ propertyNameTypeMap.insert(QLatin1String("pageId"), StringPropertyParameters(ValidationSingleLine, false));
+ // QPlainTextEdit
+ propertyNameTypeMap.insert(QLatin1String("plainText"), StringPropertyParameters(ValidationMultiLine, true));
+ }
+ return propertyNameTypeMap;
+}
+
+QDesignerPropertyEditor::QDesignerPropertyEditor(QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerPropertyEditorInterface(parent, flags),
+ m_propertyChangedForwardingBlocked(false)
+{
+ // 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);
+ }
+
+ // Check custom widgets by class.
+ const QString className = WidgetFactory::classNameOf(core, object);
+ const QDesignerCustomWidgetData customData = core->pluginManager()->customWidgetData(className);
+ if (!customData.isNull()) {
+ StringPropertyParameters customType;
+ if (customData.xmlStringPropertyType(propertyName, &customType))
+ return customType;
+ }
+
+ // Check hardcoded property ames
+ const PropertyNameTypeMap::const_iterator hit = stringPropertyTypes().constFind(propertyName);
+ if (hit != stringPropertyTypes().constEnd())
+ return hit.value();
+
+ // 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);
+ }
+
+ // Fuzzy matching
+ if (propertyName.endsWith(QLatin1String("Name")))
+ return StringPropertyParameters(ValidationSingleLine, true);
+
+ if (propertyName.endsWith(QLatin1String("ToolTip")))
+ return StringPropertyParameters(ValidationRichText, true);
+
+#ifdef Q_OS_WIN // No translation for the active X "control" property
+ if (propertyName == QLatin1String("control") && className == QLatin1String("QAxWidget"))
+ return StringPropertyParameters(ValidationSingleLine, false);
+#endif
+
+ // default to single
+ return StringPropertyParameters(ValidationSingleLine, true);
+}
+
+void QDesignerPropertyEditor::emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling)
+{
+ // Avoid duplicate signal emission - see below
+ m_propertyChangedForwardingBlocked = true;
+ emit propertyValueChanged(name, value, enableSubPropertyHandling);
+ emit propertyChanged(name, value);
+ m_propertyChangedForwardingBlocked = false;
+}
+
+void QDesignerPropertyEditor::slotPropertyChanged(const QString &name, const QVariant &value)
+{
+ // Forward signal from Integration using the old interfaces.
+ if (!m_propertyChangedForwardingBlocked)
+ emit propertyValueChanged(name, value, true);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/qdesigner_propertyeditor_p.h b/src/designer/src/lib/shared/qdesigner_propertyeditor_p.h
new file mode 100644
index 000000000..72d6f05b6
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertyeditor_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit 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);
+
+protected:
+ void emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling);
+
+private:
+ bool m_propertyChangedForwardingBlocked;
+
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERPROPERTYEDITOR_H
diff --git a/src/designer/src/lib/shared/qdesigner_propertysheet.cpp b/src/designer/src/lib/shared/qdesigner_propertysheet.cpp
new file mode 100644
index 000000000..27527da05
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertysheet.cpp
@@ -0,0 +1,1657 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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>
+#include <QtGui/QMenuBar>
+
+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
+ || propertyType(index) == QDesignerPropertySheet::PropertyText
+ || 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, QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue()));
+ else if (type == QVariant::Icon)
+ m_resourceProperties.insert(index, QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()));
+}
+
+QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const
+{
+ QVariant v = m_resourceProperties.value(index);
+ if (v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
+ return QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
+ if (v.canConvert<qdesigner_internal::PropertySheetIconValue>())
+ return QVariant::fromValue(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 ((value.canConvert<qdesigner_internal::PropertySheetPixmapValue>() && v.canConvert<qdesigner_internal::PropertySheetPixmapValue>())
+ || (value.canConvert<qdesigner_internal::PropertySheetIconValue>() && v.canConvert<qdesigner_internal::PropertySheetIconValue>()))
+ 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);
+ propertyTypeHash.insert(QLatin1String("text"), PropertyText);
+ }
+ 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/Opacity is visible only for the main container, in which case the form windows enables it on loading
+ setVisible(createFakeProperty(QLatin1String("windowModality")), false);
+ setVisible(createFakeProperty(QLatin1String("windowOpacity"), double(1.0)), false);
+ if (qobject_cast<const QToolBar *>(d->m_object)) { // prevent toolbars from being dragged off
+ createFakeProperty(QLatin1String("floatable"), QVariant(true));
+ } else {
+ if (qobject_cast<const QMenuBar *>(d->m_object)) {
+ // Keep the menu bar editable in the form even if a native menu bar is used.
+ const bool nativeMenuBarDefault = !qApp->testAttribute(Qt::AA_DontUseNativeMenuBar);
+ createFakeProperty(QLatin1String("nativeMenuBar"), QVariant(nativeMenuBarDefault));
+ }
+ }
+ 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
+{
+ // used internally
+ if (propName == QLatin1String("database") ||
+ propName == QLatin1String("buttonGroupId"))
+ return false;
+ 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 = QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
+ else if (value.type() == QVariant::Pixmap)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetPixmapValue());
+ else if (value.type() == QVariant::String)
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(value.toString()));
+ else if (value.type() == QVariant::KeySequence) {
+ const QKeySequence keySequence = qvariant_cast<QKeySequence>(value);
+ v = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
+
+ 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 = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ if (v.type() == QVariant::KeySequence)
+ v = QVariant::fromValue(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 QVariant::fromValue(value);
+ }
+
+ if (d->isKeySequenceProperty(index)) {
+ QKeySequence keyValue = qvariant_cast<QKeySequence>(metaProperty(index));
+ qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index);
+ if (keyValue != value.value()) {
+ value.setValue(keyValue);
+ d->setKeySequenceProperty(index, value); // cache it
+ }
+ return QVariant::fromValue(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()));
+ v.setValue(psflags);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::EnumKind: {
+ qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator()));
+ v.setValue(pse);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::OtherKind:
+ break;
+ }
+ return v;
+}
+
+QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const
+{
+ if (value.canConvert<qdesigner_internal::PropertySheetEnumValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value;
+
+ if (value.canConvert<qdesigner_internal::PropertySheetFlagValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value;
+
+ if (value.canConvert<qdesigner_internal::PropertySheetStringValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value();
+
+ if (value.canConvert<qdesigner_internal::PropertySheetKeySequenceValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(value).value();
+
+ if (value.canConvert<qdesigner_internal::PropertySheetPixmapValue>()) {
+ const QString path = qvariant_cast<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 (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) {
+ const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask();
+ if (mask == 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 (value.canConvert<qdesigner_internal::PropertySheetFlagValue>() || value.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
+ v = value;
+ } else if (v.canConvert<qdesigner_internal::PropertySheetFlagValue>()) {
+ qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v);
+ f.value = value.toInt();
+ v.setValue(f);
+ Q_ASSERT(value.type() == QVariant::Int);
+ } else if (v.canConvert<qdesigner_internal::PropertySheetEnumValue>()) {
+ qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v);
+ e.value = value.toInt();
+ v.setValue(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) || isDefaultDynamicProperty(index)) {
+ if (d->isResourceProperty(index))
+ d->setResourceProperty(index, value);
+ if (d->isStringProperty(index))
+ d->setStringProperty(index, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qvariant_cast<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, qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qvariant_cast<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 = qvariant_cast<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;
+ v.setValue(e);
+ setFakeProperty(idx, v);
+ } else {
+ e.value = Qt::NoFocus;
+ QVariant v;
+ v.setValue(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)) {
+ qdesigner_internal::PropertySheetStringValue value;
+ // Main container: Reset to stored class name as not to change the file names generated by uic.
+ if (propertyName(index) == QLatin1String("objectName")) {
+ const QVariant classNameDefaultV = d->m_object->property("_q_classname");
+ if (classNameDefaultV.isValid())
+ value.setValue(classNameDefaultV.toString());
+ }
+ setProperty(index, QVariant::fromValue(value));
+ return true;
+ }
+ if (d->isKeySequenceProperty(index))
+ setProperty(index, QVariant::fromValue(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 defaultValue = d->m_info.value(index).defaultValue;
+ QVariant newValue = defaultValue;
+ if (d->isStringProperty(index)) {
+ newValue = QVariant::fromValue(qdesigner_internal::PropertySheetStringValue(newValue.toString()));
+ } else if (d->isKeySequenceProperty(index)) {
+ const QKeySequence keySequence = qvariant_cast<QKeySequence>(newValue);
+ newValue = QVariant::fromValue(qdesigner_internal::PropertySheetKeySequenceValue(keySequence));
+ }
+ if (oldValue == newValue)
+ return true;
+ d->m_object->setProperty(propName.toUtf8(), defaultValue);
+ 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;
+}
+
+// Determine the "designable" state of a property. Properties, which have
+// a per-object boolean test function that returns false are shown in
+// disabled state ("checked" depending on "checkable", etc.)
+// Properties, which are generally not designable independent
+// of the object are not shown at all.
+enum DesignableState { PropertyIsDesignable,
+ // Object has a Designable test function that returns false.
+ PropertyOfObjectNotDesignable,
+ PropertyNotDesignable };
+
+static inline DesignableState designableState(const QDesignerMetaPropertyInterface *p, const QObject *object)
+{
+ if (p->attributes(object) & QDesignerMetaPropertyInterface::DesignableAttribute)
+ return PropertyIsDesignable;
+ return (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute) ?
+ PropertyOfObjectNotDesignable : PropertyNotDesignable;
+}
+
+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)) {
+ switch (type) {
+ case PropertyWindowModality: // Hidden for child widgets
+ case PropertyWindowOpacity:
+ return d->m_info.value(index).visible;
+ default:
+ break;
+ }
+ 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: Hide only statically not designable properties
+ return designableState(p, d->m_object) != PropertyNotDesignable;
+}
+
+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;
+
+ // Enable setting of properties for statically non-designable properties
+ // as this might be done via TaskMenu/Cursor::setProperty. Note that those
+ // properties are not visible.
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ return (p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess) &&
+ designableState(p, d->m_object) != PropertyOfObjectNotDesignable;
+}
+
+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/src/designer/src/lib/shared/qdesigner_propertysheet_p.h b/src/designer/src/lib/shared/qdesigner_propertysheet_p.h
new file mode 100644
index 000000000..67d195b65
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_propertysheet_p.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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,
+ PropertyText
+ };
+
+ 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/src/designer/src/lib/shared/qdesigner_qsettings.cpp b/src/designer/src/lib/shared/qdesigner_qsettings.cpp
new file mode 100644
index 000000000..65c78362d
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_qsettings.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_qsettings_p.h b/src/designer/src/lib/shared/qdesigner_qsettings_p.h
new file mode 100644
index 000000000..e0586cc65
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_qsettings_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_stackedbox.cpp b/src/designer/src/lib/shared/qdesigner_stackedbox.cpp
new file mode 100644
index 000000000..0206e9709
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_stackedbox.cpp
@@ -0,0 +1,399 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(count);
+ 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);
+ } else {
+ QAction *insertPageAction = popup->addAction(tr("Insert Page"));
+ connect(insertPageAction, SIGNAL(triggered()), this, SLOT(addPage()));
+ }
+ 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/src/designer/src/lib/shared/qdesigner_stackedbox_p.h b/src/designer/src/lib/shared/qdesigner_stackedbox_p.h
new file mode 100644
index 000000000..d4b6db449
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_stackedbox_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_tabwidget.cpp b/src/designer/src/lib/shared/qdesigner_tabwidget.cpp
new file mode 100644
index 000000000..6110deaba
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_tabwidget.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 = m_tabWidget->findChildren<QTabBar *>();
+ 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);
+ 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);
+ } else {
+ QAction *insertPageAction = popup->addAction(tr("Insert Page"));
+ connect(insertPageAction, SIGNAL(triggered()), this, SLOT(addPage()));
+ }
+ 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";
+static const char *tabMovableKey = "movable";
+
+QTabWidgetPropertySheet::QTabWidgetPropertySheet(QTabWidget *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_tabWidget(object)
+{
+ createFakeProperty(QLatin1String(currentTabTextKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentTabNameKey), QString());
+ createFakeProperty(QLatin1String(currentTabIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()));
+ if (formWindowBase())
+ formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentTabIconKey)));
+ createFakeProperty(QLatin1String(currentTabToolTipKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentTabWhatsThisKey), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()));
+ // Prevent the tab widget's drag and drop handling from interfering with Designer's
+ createFakeProperty(QLatin1String(tabMovableKey), QVariant(false));
+}
+
+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 = qvariant_cast<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 = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value);
+ break;
+ case PropertyCurrentTabToolTip:
+ m_tabWidget->setTabToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].tooltip = qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyCurrentTabWhatsThis:
+ m_tabWidget->setTabWhatsThis(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].whatsthis = qvariant_cast<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 QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
+ if (tabWidgetProperty == PropertyCurrentTabText)
+ return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ if (tabWidgetProperty == PropertyCurrentTabToolTip)
+ return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ if (tabWidgetProperty == PropertyCurrentTabWhatsThis)
+ return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ return QVariant(QString());
+ }
+
+ // index-dependent
+ switch (tabWidgetProperty) {
+ case PropertyCurrentTabText:
+ return QVariant::fromValue(m_pageToData.value(currentWidget).text);
+ case PropertyCurrentTabName:
+ return currentWidget->objectName();
+ case PropertyCurrentTabIcon:
+ return QVariant::fromValue(m_pageToData.value(currentWidget).icon);
+ case PropertyCurrentTabToolTip:
+ return QVariant::fromValue(m_pageToData.value(currentWidget).tooltip);
+ case PropertyCurrentTabWhatsThis:
+ return QVariant::fromValue(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/src/designer/src/lib/shared/qdesigner_tabwidget_p.h b/src/designer/src/lib/shared/qdesigner_tabwidget_p.h
new file mode 100644
index 000000000..23140a600
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_tabwidget_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_taskmenu.cpp b/src/designer/src/lib/shared/qdesigner_taskmenu.cpp
new file mode 100644
index 000000000..5a9ace4b9
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_taskmenu.cpp
@@ -0,0 +1,912 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_taskmenu_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_command2_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
+ = qvariant_cast<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
+
+namespace qdesigner_internal {
+
+// Sub menu displaying the alignment options of a widget in a managed
+// grid/box layout cell.
+class LayoutAlignmentMenu {
+public:
+ explicit LayoutAlignmentMenu(QObject *parent);
+
+ QAction *subMenuAction() const { return m_subMenuAction; }
+
+ void connect(QObject *receiver, const char *aSlot);
+
+ // Set up enabled state and checked actions according to widget (managed box/grid)
+ bool setAlignment(const QDesignerFormEditorInterface *core, QWidget *w);
+
+ // Return the currently checked alignment
+ Qt::Alignment alignment() const;
+
+private:
+ enum Actions { HorizNone, Left, HorizCenter, Right, VerticalNone, Top, VerticalCenter, Bottom };
+ static QAction *createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag);
+
+ QAction *m_subMenuAction;
+ QActionGroup *m_horizGroup;
+ QActionGroup *m_verticalGroup;
+ QAction *m_actions[Bottom + 1];
+};
+
+QAction *LayoutAlignmentMenu::createAction(const QString &text, int data, QMenu *menu, QActionGroup *ag)
+{
+ QAction * a = new QAction(text, 0);
+ a->setCheckable(true);
+ a->setData(QVariant(data));
+ menu->addAction(a);
+ ag->addAction(a);
+ return a;
+}
+
+LayoutAlignmentMenu::LayoutAlignmentMenu(QObject *parent) :
+ m_subMenuAction(new QAction(QDesignerTaskMenu::tr("Layout Alignment"), parent)),
+ m_horizGroup(new QActionGroup(parent)),
+ m_verticalGroup(new QActionGroup(parent))
+{
+ m_horizGroup->setExclusive(true);
+ m_verticalGroup->setExclusive(true);
+
+ QMenu *menu = new QMenu;
+ m_subMenuAction->setMenu(menu);
+
+ m_actions[HorizNone] = createAction(QDesignerTaskMenu::tr("No Horizontal Alignment"), 0, menu, m_horizGroup);
+ m_actions[Left] = createAction(QDesignerTaskMenu::tr("Left"), Qt::AlignLeft, menu, m_horizGroup);
+ m_actions[HorizCenter] = createAction(QDesignerTaskMenu::tr("Center Horizontally"), Qt::AlignHCenter, menu, m_horizGroup);
+ m_actions[Right] = createAction(QDesignerTaskMenu::tr("Right"), Qt::AlignRight, menu, m_horizGroup);
+ menu->addSeparator();
+ m_actions[VerticalNone] = createAction(QDesignerTaskMenu::tr("No Vertical Alignment"), 0, menu, m_verticalGroup);
+ m_actions[Top] = createAction(QDesignerTaskMenu::tr("Top"), Qt::AlignTop, menu, m_verticalGroup);
+ m_actions[VerticalCenter] = createAction(QDesignerTaskMenu::tr("Center Vertically"), Qt::AlignVCenter, menu, m_verticalGroup);
+ m_actions[Bottom] = createAction(QDesignerTaskMenu::tr("Bottom"), Qt::AlignBottom, menu, m_verticalGroup);
+}
+
+void LayoutAlignmentMenu::connect(QObject *receiver, const char *aSlot)
+{
+ QObject::connect(m_horizGroup, SIGNAL(triggered(QAction*)), receiver, aSlot);
+ QObject::connect(m_verticalGroup, SIGNAL(triggered(QAction*)), receiver, aSlot);
+}
+
+bool LayoutAlignmentMenu::setAlignment(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ bool enabled;
+ const Qt::Alignment alignment = LayoutAlignmentCommand::alignmentOf(core, w, &enabled);
+ if (!enabled) {
+ m_subMenuAction->setEnabled(false);
+ m_actions[HorizNone]->setChecked(true);
+ m_actions[VerticalNone]->setChecked(true);
+ return false;
+ }
+ // Get alignment
+ switch (alignment & Qt::AlignHorizontal_Mask) {
+ case Qt::AlignLeft:
+ m_actions[Left]->setChecked(true);
+ break;
+ case Qt::AlignHCenter:
+ m_actions[HorizCenter]->setChecked(true);
+ break;
+ case Qt::AlignRight:
+ m_actions[Right]->setChecked(true);
+ break;
+ default:
+ m_actions[HorizNone]->setChecked(true);
+ break;
+ }
+ switch (alignment & Qt::AlignVertical_Mask) {
+ case Qt::AlignTop:
+ m_actions[Top]->setChecked(true);
+ break;
+ case Qt::AlignVCenter:
+ m_actions[VerticalCenter]->setChecked(true);
+ break;
+ case Qt::AlignBottom:
+ m_actions[Bottom]->setChecked(true);
+ break;
+ default:
+ m_actions[VerticalNone]->setChecked(true);
+ break;
+ }
+ return true;
+}
+
+Qt::Alignment LayoutAlignmentMenu::alignment() const
+{
+ Qt::Alignment alignment = 0;
+ if (const QAction *horizAction = m_horizGroup->checkedAction())
+ if (const int horizAlign = horizAction->data().toInt())
+ alignment |= static_cast<Qt::Alignment>(horizAlign);
+ if (const QAction *vertAction = m_verticalGroup->checkedAction())
+ if (const int vertAlign = vertAction->data().toInt())
+ alignment |= static_cast<Qt::Alignment>(vertAlign);
+ return alignment;
+}
+
+// -------------- 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;
+ LayoutAlignmentMenu m_layoutAlignmentMenu;
+ 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_layoutAlignmentMenu(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*)));
+ d->m_layoutAlignmentMenu.connect(this, SLOT(slotLayoutAlignment()));
+}
+
+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);
+ if (d->m_layoutAlignmentMenu.setAlignment(formWindow->core(), d->m_widget))
+ actions.append(d->m_layoutAlignmentMenu.subMenuAction());
+
+ 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, QVariant::fromValue(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 = qvariant_cast<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, QVariant::fromValue(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 = qvariant_cast<QStringList>(selectedItem->data(0, Qt::UserRole));
+
+ // TODO: Check whether 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 << '.';
+ }
+}
+
+void QDesignerTaskMenu::slotLayoutAlignment()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ const Qt::Alignment newAlignment = d->m_layoutAlignmentMenu.alignment();
+ LayoutAlignmentCommand *cmd = new LayoutAlignmentCommand(fw);
+ if (cmd->init(d->m_widget, newAlignment)) {
+ fw->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ }
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/qdesigner_taskmenu_p.h b/src/designer/src/lib/shared/qdesigner_taskmenu_p.h
new file mode 100644
index 000000000..b86ce69b1
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_taskmenu_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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);
+ void slotLayoutAlignment();
+
+private:
+ QDesignerTaskMenuPrivate *d;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QWidget, QDesignerTaskMenu> QDesignerTaskMenuFactory;
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TASKMENU_H
diff --git a/src/designer/src/lib/shared/qdesigner_toolbar.cpp b/src/designer/src/lib/shared/qdesigner_toolbar.cpp
new file mode 100644
index 000000000..0fe730384
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_toolbar.cpp
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <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);
+ itemData.setValue(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);
+ itemData.setValue(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);
+ itemData.setValue(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);
+}
+
+//that's a trick to get access to the initStyleOption which is a protected member
+class FriendlyToolBar : public QToolBar {
+public:
+ friend class ToolBarEventFilter;
+};
+
+QRect ToolBarEventFilter::handleArea(const QToolBar *tb)
+{
+ QStyleOptionToolBar opt;
+ static_cast<const FriendlyToolBar*>(tb)->initStyleOption(&opt);
+ return tb->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, tb);
+}
+
+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 (tb->layoutDirection()) {
+ case Qt::LayoutDirectionAuto: // Should never happen
+ 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/src/designer/src/lib/shared/qdesigner_toolbar_p.h b/src/designer/src/lib/shared/qdesigner_toolbar_p.h
new file mode 100644
index 000000000..7a38ec773
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_toolbar_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_toolbox.cpp b/src/designer/src/lib/shared/qdesigner_toolbox.cpp
new file mode 100644
index 000000000..675e98c36
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_toolbox.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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), QVariant::fromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentItemNameKey), QString());
+ createFakeProperty(QLatin1String(currentItemIconKey), QVariant::fromValue(qdesigner_internal::PropertySheetIconValue()));
+ if (formWindowBase())
+ formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey)));
+ createFakeProperty(QLatin1String(currentItemToolTipKey), QVariant::fromValue(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 = qvariant_cast<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 = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value);
+ break;
+ case PropertyCurrentItemToolTip:
+ m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].tooltip = qvariant_cast<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 QVariant::fromValue(qdesigner_internal::PropertySheetIconValue());
+ if (toolBoxProperty == PropertyCurrentItemText)
+ return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ if (toolBoxProperty == PropertyCurrentItemToolTip)
+ return QVariant::fromValue(qdesigner_internal::PropertySheetStringValue());
+ return QVariant(QString());
+ }
+
+ // index-dependent
+ switch (toolBoxProperty) {
+ case PropertyCurrentItemText:
+ return QVariant::fromValue(m_pageToData.value(currentWidget).text);
+ case PropertyCurrentItemName:
+ return currentWidget->objectName();
+ case PropertyCurrentItemIcon:
+ return QVariant::fromValue(m_pageToData.value(currentWidget).icon);
+ case PropertyCurrentItemToolTip:
+ return QVariant::fromValue(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/src/designer/src/lib/shared/qdesigner_toolbox_p.h b/src/designer/src/lib/shared/qdesigner_toolbox_p.h
new file mode 100644
index 000000000..f9d390ed0
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_toolbox_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_utils.cpp b/src/designer/src/lib/shared/qdesigner_utils.cpp
new file mode 100644
index 000000000..1c6c8547c
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_utils.cpp
@@ -0,0 +1,848 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtCore/QDir>
+#include <QtCore/QProcess>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QQueue>
+#include <QtCore/QSharedData>
+
+#include <QtGui/QApplication>
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+#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 (v.canConvert<PropertySheetIconValue>())
+ item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)));
+ }
+ }
+
+ void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item)
+ {
+ if (!item)
+ return;
+
+ const QVariant v = item->data(Qt::DecorationPropertyRole);
+ if (v.canConvert<PropertySheetIconValue>())
+ item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)));
+ }
+
+ void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item)
+ {
+ if (!item)
+ return;
+
+ const QVariant v = item->data(Qt::DecorationPropertyRole);
+ if (v.canConvert<PropertySheetIconValue>())
+ item->setIcon(iconCache->icon(qvariant_cast<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 (v.canConvert<PropertySheetIconValue>()) {
+ QIcon icon = iconCache->icon(qvariant_cast<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
+
+ class PropertySheetIconValueData : public QSharedData {
+ public:
+ PropertySheetIconValue::ModeStateToPixmapMap m_paths;
+ QString m_theme;
+ };
+
+ PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) :
+ m_data(new PropertySheetIconValueData)
+ {
+ setPixmap(QIcon::Normal, QIcon::Off, pixmap);
+ }
+
+ PropertySheetIconValue::PropertySheetIconValue() :
+ m_data(new PropertySheetIconValueData)
+ {
+ }
+
+ PropertySheetIconValue::~PropertySheetIconValue()
+ {
+ }
+
+ PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) :
+ m_data(rhs.m_data)
+ {
+ }
+
+ PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs)
+ {
+ if (this != &rhs)
+ m_data.operator=(rhs.m_data);
+ return *this;
+ }
+
+ bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const
+ {
+ return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths;
+ }
+
+ bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const
+ {
+ if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme))
+ return themeCmp < 0;
+ QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths);
+ QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->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;
+ }
+
+ bool PropertySheetIconValue::isEmpty() const
+ {
+ return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty();
+ }
+
+ QString PropertySheetIconValue::theme() const
+ {
+ return m_data->m_theme;
+ }
+
+ void PropertySheetIconValue::setTheme(const QString &t)
+ {
+ m_data->m_theme = t;
+ }
+
+ PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const
+ {
+ const ModeStateKey pair = qMakePair(mode, state);
+ return m_data->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_data->m_paths.remove(pair);
+ else
+ m_data->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
+ {
+ typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
+
+ QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value);
+ if (it != m_cache.constEnd())
+ return it.value();
+
+ // Match on the theme first if it is available.
+ if (!value.theme().isEmpty()) {
+ const QString theme = value.theme();
+ if (QIcon::hasThemeIcon(theme)) {
+ const QIcon themeIcon = QIcon::fromTheme(theme);
+ m_cache.insert(value, themeIcon);
+ return themeIcon;
+ }
+ }
+
+ QIcon icon;
+ const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths();
+ const ModeStateToPixmapMapConstIt cend = paths.constEnd();
+ for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) {
+ const QPair<QIcon::Mode, QIcon::State> pair = it.key();
+ icon.addFile(it.value().path(), QSize(), 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);
+ }
+
+
+ /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the
+ * various states/modes and the theme) a flag bit (see QFont) so that they
+ * can be handled individually when assigning property values to
+ * multiselections in the set-property-commands (that is, do not clobber
+ * other subproperties when assigning just one).
+ * Provide back-and-forth mapping functions for the icon states. */
+
+ enum IconSubPropertyMask {
+ NormalOffIconMask = 0x01,
+ NormalOnIconMask = 0x02,
+ DisabledOffIconMask = 0x04,
+ DisabledOnIconMask = 0x08,
+ ActiveOffIconMask = 0x10,
+ ActiveOnIconMask = 0x20,
+ SelectedOffIconMask = 0x40,
+ SelectedOnIconMask = 0x80,
+ ThemeIconMask = 0x10000
+ };
+
+ static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state)
+ {
+ switch (mode) {
+ case QIcon::Disabled:
+ return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask;
+ case QIcon::Active:
+ return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask;
+ case QIcon::Selected:
+ return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask;
+ case QIcon::Normal:
+ break;
+ }
+ return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask;
+ }
+
+ static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag)
+ {
+ switch (flag) {
+ case NormalOnIconMask:
+ return qMakePair(QIcon::Normal, QIcon::On);
+ case DisabledOffIconMask:
+ return qMakePair(QIcon::Disabled, QIcon::Off);
+ case DisabledOnIconMask:
+ return qMakePair(QIcon::Disabled, QIcon::On);
+ case ActiveOffIconMask:
+ return qMakePair(QIcon::Active, QIcon::Off);
+ case ActiveOnIconMask:
+ return qMakePair(QIcon::Active, QIcon::On);
+ case SelectedOffIconMask:
+ return qMakePair(QIcon::Selected, QIcon::Off);
+ case SelectedOnIconMask:
+ return qMakePair(QIcon::Selected, QIcon::On);
+ case NormalOffIconMask:
+ default:
+ break;
+ }
+ return qMakePair(QIcon::Normal, QIcon::Off);
+ }
+
+ uint PropertySheetIconValue::mask() const
+ {
+ typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
+
+ uint flags = 0;
+ const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd();
+ for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it)
+ flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second);
+ if (!m_data->m_theme.isEmpty())
+ flags |= ThemeIconMask;
+ return flags;
+ }
+
+ uint PropertySheetIconValue::compare(const PropertySheetIconValue &other) const
+ {
+ uint diffMask = mask() | other.mask();
+ for (int i = 0; i < 8; i++) {
+ const uint flag = 1 << i;
+ if (diffMask & flag) { // if state is set in both icons, compare the values
+ const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag);
+ if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second))
+ diffMask &= ~flag;
+ }
+ }
+ if ((diffMask & ThemeIconMask) && theme() == other.theme())
+ diffMask &= ~ThemeIconMask;
+ return diffMask;
+ }
+
+ PropertySheetIconValue PropertySheetIconValue::themed() const
+ {
+ PropertySheetIconValue rc(*this);
+ rc.m_data->m_paths.clear();
+ return rc;
+ }
+
+ PropertySheetIconValue PropertySheetIconValue::unthemed() const
+ {
+ PropertySheetIconValue rc(*this);
+ rc.m_data->m_theme.clear();
+ return rc;
+ }
+
+ 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 = subPropertyFlagToIconModeState(flag);
+ setPixmap(state.first, state.second, other.pixmap(state.first, state.second));
+ }
+ }
+ if (mask & ThemeIconMask)
+ setTheme(other.theme());
+ }
+
+ const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const
+ {
+ return m_data->m_paths;
+ }
+
+ QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p)
+ {
+ typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
+
+ QDebug nospace = d.nospace();
+ nospace << "PropertySheetIconValue theme='" << p.theme() << "' ";
+
+ const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths();
+ const ModeStateToPixmapMapConstIt cend = paths.constEnd();
+ for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it)
+ nospace << " mode=" << it.key().first << ",state=" << it.key().second
+ << ",'" << it.value().path() << '\'';
+ nospace << " mask=0x" << QString::number(p.mask(), 16);
+ return d;
+ }
+
+ 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/src/designer/src/lib/shared/qdesigner_utils_p.h b/src/designer/src/lib/shared/qdesigner_utils_p.h
new file mode 100644
index 000000000..1e48cf8db
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_utils_p.h
@@ -0,0 +1,499 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/QSharedDataPointer>
+#include <QtCore/QMap>
+#include <QtGui/QMainWindow>
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+
+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 PropertySheetIconValueData;
+
+class QDESIGNER_SHARED_EXPORT PropertySheetIconValue
+{
+ public:
+ PropertySheetIconValue(const PropertySheetPixmapValue &pixmap);
+ PropertySheetIconValue();
+ ~PropertySheetIconValue();
+ PropertySheetIconValue(const PropertySheetIconValue &);
+ PropertySheetIconValue &operator=(const 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;
+
+ bool isEmpty() const;
+
+ QString theme() const;
+ void setTheme(const QString &);
+
+ 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);
+
+ // Convenience accessors to get themed/unthemed icons.
+ PropertySheetIconValue themed() const;
+ PropertySheetIconValue unthemed() const;
+
+ typedef QPair<QIcon::Mode, QIcon::State> ModeStateKey;
+ typedef QMap<ModeStateKey, PropertySheetPixmapValue> ModeStateToPixmapMap;
+
+ const ModeStateToPixmapMap &paths() const;
+
+private:
+ bool equals(const PropertySheetIconValue &rhs) const;
+ QSharedDataPointer<PropertySheetIconValueData> m_data;
+};
+
+QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &);
+
+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:
+ explicit 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:
+ explicit 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:
+ explicit PropertySheetKeySequenceValue(const QKeySequence &value = QKeySequence(),
+ bool translatable = true,
+ const QString &disambiguation = QString(),
+ const QString &comment = QString());
+ explicit 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 (value.canConvert<PropertySheetEnumValue>()) {
+ if (ok)
+ *ok = true;
+ return qvariant_cast<PropertySheetEnumValue>(value).value;
+ }
+ else if (value.canConvert<PropertySheetFlagValue>()) {
+ if (ok)
+ *ok = true;
+ return qvariant_cast<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/src/designer/src/lib/shared/qdesigner_widget.cpp b/src/designer/src/lib/shared/qdesigner_widget.cpp
new file mode 100644
index 000000000..0368d5337
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widget.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_widget_p.h b/src/designer/src/lib/shared/qdesigner_widget_p.h
new file mode 100644
index 000000000..bb511ae4b
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widget_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qdesigner_widgetbox.cpp b/src/designer/src/lib/shared/qdesigner_widgetbox.cpp
new file mode 100644
index 000000000..154b2d61d
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widgetbox.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_widgetbox_p.h b/src/designer/src/lib/shared/qdesigner_widgetbox_p.h
new file mode 100644
index 000000000..d0a1285db
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widgetbox_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 };
+
+ explicit 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/src/designer/src/lib/shared/qdesigner_widgetitem.cpp b/src/designer/src/lib/shared/qdesigner_widgetitem.cpp
new file mode 100644
index 000000000..a3041ad83
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widgetitem.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qdesigner_widgetitem_p.h b/src/designer/src/lib/shared/qdesigner_widgetitem_p.h
new file mode 100644
index 000000000..f79dbc5a1
--- /dev/null
+++ b/src/designer/src/lib/shared/qdesigner_widgetitem_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qlayout_widget.cpp b/src/designer/src/lib/shared/qlayout_widget.cpp
new file mode 100644
index 000000000..66e7a795b
--- /dev/null
+++ b/src/designer/src/lib/shared/qlayout_widget.cpp
@@ -0,0 +1,2107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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. Datatype storing 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;
+ typedef QMap<QWidget *, Qt::Alignment> WidgetAlignmentMap;
+
+ WidgetItemMap widgetItemMap;
+ WidgetAlignmentMap widgetAlignmentMap;
+
+ 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));
+ if (item->alignment())
+ widgetAlignmentMap.insert(item->widget(), item->alignment());
+ }
+ }
+ }
+
+ 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();
+ const Qt::Alignment alignment = widgetAlignmentMap.value(it.key()->widget(), Qt::Alignment(0));
+ grid->addItem(it.key(), info.y(), info.x(), info.height(), info.width(), alignment);
+ }
+ // 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] && 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/src/designer/src/lib/shared/qlayout_widget_p.h b/src/designer/src/lib/shared/qlayout_widget_p.h
new file mode 100644
index 000000000..a87679e75
--- /dev/null
+++ b/src/designer/src/lib/shared/qlayout_widget_p.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qscripthighlighter.cpp b/src/designer/src/lib/shared/qscripthighlighter.cpp
new file mode 100644
index 000000000..67555f39e
--- /dev/null
+++ b/src/designer/src/lib/shared/qscripthighlighter.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/qscripthighlighter_p.h b/src/designer/src/lib/shared/qscripthighlighter_p.h
new file mode 100644
index 000000000..7e067c299
--- /dev/null
+++ b/src/designer/src/lib/shared/qscripthighlighter_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/qsimpleresource.cpp b/src/designer/src/lib/shared/qsimpleresource.cpp
new file mode 100644
index 000000000..178ba3e18
--- /dev/null
+++ b/src/designer/src/lib/shared/qsimpleresource.cpp
@@ -0,0 +1,418 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimpleresource_p.h"
+#include "widgetfactory_p.h"
+#include "widgetdatabase_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>
+#include <QtCore/QCoreApplication>
+
+
+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));
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ // Disable scripting in the editors.
+ formScriptRunner()-> setOptions(QFormScriptRunner::DisableScripts);
+#endif
+}
+
+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;
+}
+
+// Custom widgets handling helpers
+
+// Add unique fake slots and signals to lists
+bool QSimpleResource::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;
+}
+
+void QSimpleResource::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);
+ }
+}
+
+// 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.
+
+void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core,
+ QList<DomCustomWidget*>& custom_widget_list)
+{
+ QDesignerWidgetDataBaseInterface *db = 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(QCoreApplication::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, QCoreApplication::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 "container" is not set properly:
+ // Apply "container" 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 QSimpleResource::handleDomCustomWidgets(const QDesignerFormEditorInterface *core,
+ const DomCustomWidgets *dom_custom_widgets)
+{
+ if (dom_custom_widgets == 0)
+ return;
+ QList<DomCustomWidget*> 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(core, 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(core, custom_widget_list);
+}
+
+// ------------ 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/src/designer/src/lib/shared/qsimpleresource_p.h b/src/designer/src/lib/shared/qsimpleresource_p.h
new file mode 100644
index 000000000..597b101cd
--- /dev/null
+++ b/src/designer/src/lib/shared/qsimpleresource_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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"
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class DomScript;
+class DomCustomWidgets;
+class DomCustomWidget;
+class DomSlots;
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class WidgetDataBaseItem;
+
+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);
+
+ // Implementation for FormBuilder::createDomCustomWidgets() that adds
+ // the custom widgets to the widget database
+ static void handleDomCustomWidgets(const QDesignerFormEditorInterface *core,
+ const DomCustomWidgets *dom_custom_widgets);
+
+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);
+
+ static bool addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals);
+
+private:
+ static void addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core,
+ QList<DomCustomWidget*>& custom_widget_list);
+ static void addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item);
+
+ 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/src/designer/src/lib/shared/qtresourceeditordialog.cpp b/src/designer/src/lib/shared/qtresourceeditordialog.cpp
new file mode 100644
index 000000000..9162b097d
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourceeditordialog.cpp
@@ -0,0 +1,2223 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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*,QString)),
+ this, SLOT(slotResourcePrefixChanged(QtResourcePrefix*)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceLanguageChanged(QtResourcePrefix*,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*,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(QPoint)),
+ this, SLOT(slotListWidgetContextMenuRequested(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(QPoint)),
+ this, SLOT(slotTreeViewContextMenuRequested(QPoint)));
+ connect(d_ptr->m_treeModel, SIGNAL(itemChanged(QStandardItem*)),
+ this, SLOT(slotTreeViewItemChanged(QStandardItem*)));
+ connect(d_ptr->m_treeSelection, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(slotCurrentTreeViewItemChanged(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();
+}
+
+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/src/designer/src/lib/shared/qtresourceeditordialog.ui b/src/designer/src/lib/shared/qtresourceeditordialog.ui
new file mode 100644
index 000000000..fa760d9a1
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/qtresourceeditordialog_p.h b/src/designer/src/lib/shared/qtresourceeditordialog_p.h
new file mode 100644
index 000000000..eef3bf540
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourceeditordialog_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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 <QtCore/QScopedPointer>
+#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();
+
+ QScopedPointer<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/src/designer/src/lib/shared/qtresourcemodel.cpp b/src/designer/src/lib/shared/qtresourcemodel.cpp
new file mode 100644
index 000000000..ca2fb7882
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourcemodel.cpp
@@ -0,0 +1,650 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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()
+{
+}
+
+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 (!library.output(buffer, errorDevice))
+ break;
+
+ *errorCount = library.failedResources().size();
+ *contents = resMap.keys();
+
+ if (resMap.empty())
+ break;
+
+ 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
+ const QByteArray *data = itRcc.value();
+ if (data) {
+ if (!QResource::registerResource(reinterpret_cast<const uchar *>(data->constData()))) {
+ qWarning() << "** 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
+ const QByteArray *data = itRcc.value();
+ if (data) {
+ if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData())))
+ qWarning() << "** 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++;
+ 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);
+
+ 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 (array && !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)
+{
+ if (!enable) {
+ m_fileWatcher->removePath(path);
+ 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(QString)),
+ this, SLOT(slotFileChanged(QString)));
+}
+
+QtResourceModel::~QtResourceModel()
+{
+ blockSignals(true);
+ QList<QtResourceSet *> resourceList = resourceSets();
+ QListIterator<QtResourceSet *> it(resourceList);
+ while (it.hasNext())
+ removeResourceSet(it.next());
+ blockSignals(false);
+}
+
+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/src/designer/src/lib/shared/qtresourcemodel_p.h b/src/designer/src/lib/shared/qtresourcemodel_p.h
new file mode 100644
index 000000000..b1ddcca4a
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourcemodel_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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>
+#include <QtCore/QScopedPointer>
+
+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;
+
+ QScopedPointer<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;
+
+ QScopedPointer<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/src/designer/src/lib/shared/qtresourceview.cpp b/src/designer/src/lib/shared/qtresourceview.cpp
new file mode 100644
index 000000000..040027355
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourceview.cpp
@@ -0,0 +1,906 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractsettings_p.h"
+#include "qtresourceview_p.h"
+#include "qtresourcemodel_p.h"
+#include "qtresourceeditordialog_p.h"
+#include "iconloader_p.h"
+#include "filterwidget_p.h" // For FilterWidget
+
+#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 slotFilterChanged(const QString &pattern);
+ void createPaths();
+ QTreeWidgetItem *createPath(const QString &path, QTreeWidgetItem *parent);
+ void createResources(const QString &path);
+ void storeExpansionState();
+ void applyExpansionState();
+ void restoreSettings();
+ void saveSettings();
+ void updateActions();
+ void filterOutResources();
+
+ QPixmap makeThumbnail(const QPixmap &pix) const;
+
+ QDesignerFormEditorInterface *m_core;
+ QtResourceModel *m_resourceModel;
+ QToolBar *m_toolBar;
+ qdesigner_internal::FilterWidget *m_filterWidget;
+ QTreeWidget *m_treeWidget;
+ QListWidget *m_listWidget;
+ QSplitter *m_splitter;
+ QMap<QString, QStringList> m_pathToContents; // full path to contents file names (full path to its resource filenames)
+ QMap<QString, QString> m_pathToParentPath; // full path to full parent path
+ QMap<QString, QStringList> m_pathToSubPaths; // full path to full sub paths
+ 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;
+ QString m_filterPattern;
+};
+
+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::slotFilterChanged(const QString &pattern)
+{
+ m_filterPattern = pattern;
+ filterOutResources();
+}
+
+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);
+ m_filterWidget->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_pathToParentPath.clear();
+ m_pathToSubPaths.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);
+ filterOutResources();
+}
+
+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;
+
+ // Resource root up until 4.6 was ':', changed to ":/" as of 4.7
+ const QString root(QLatin1String(":/"));
+
+ 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 (!m_pathToParentPath.contains(dirPath) && dirPath != root) { // create all parent paths
+ const QFileInfo fd(dirPath);
+ const QString parentDirPath = fd.absolutePath();
+ m_pathToParentPath[dirPath] = parentDirPath;
+ m_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 = m_pathToSubPaths.value(path);
+ QStringListIterator itSubPaths(subPaths);
+ while (itSubPaths.hasNext())
+ pathToParentItemQueue.enqueue(qMakePair(itSubPaths.next(), item));
+ }
+}
+
+void QtResourceViewPrivate::filterOutResources()
+{
+ QMap<QString, bool> pathToMatchingContents; // true means the path has any matching contents
+ QMap<QString, bool> pathToVisible; // true means the path has to be shown
+
+ // 1) we go from root path recursively.
+ // 2) we check every path if it contains at least one matching resource - if empty we add it
+ // to pathToMatchingContents and pathToVisible with false, if non empty
+ // we add it with true and change every parent path in pathToVisible to true.
+ // 3) we hide these items which has pathToVisible value false.
+
+ const bool matchAll = m_filterPattern.isEmpty();
+ const QString root(QLatin1String(":/"));
+
+ QQueue<QString> pathQueue;
+ pathQueue.enqueue(root);
+ while (!pathQueue.isEmpty()) {
+ const QString path = pathQueue.dequeue();
+
+ QStringList fileNames = m_pathToContents.value(path);
+ QStringListIterator it(fileNames);
+ bool hasContents = matchAll;
+ if (!matchAll) { // the case filter is not empty - we check if the path contains anything
+ while (it.hasNext()) {
+ QString fileName = it.next();
+ hasContents = fileName.contains(m_filterPattern, Qt::CaseInsensitive);
+ if (hasContents) // the path contains at least one resource which matches the filter
+ break;
+ }
+ }
+
+ pathToMatchingContents[path] = hasContents;
+ pathToVisible[path] = hasContents;
+
+ if (hasContents) { // if the path is going to be shown we need to show all its parent paths
+ QString parentPath = m_pathToParentPath.value(path);
+ while (!parentPath.isEmpty()) {
+ QString p = parentPath;
+ if (pathToVisible.value(p)) // parent path is already shown, we break the loop
+ break;
+ pathToVisible[p] = true;
+ parentPath = m_pathToParentPath.value(p);
+ }
+ }
+
+ QStringList subPaths = m_pathToSubPaths.value(path); // we do the same for children paths
+ QStringListIterator itSubPaths(subPaths);
+ while (itSubPaths.hasNext())
+ pathQueue.enqueue(itSubPaths.next());
+ }
+
+ // we setup here new path and resource to be activated
+ const QString currentPath = m_itemToPath.value(m_treeWidget->currentItem());
+ QString newCurrentPath = currentPath;
+ QString currentResource = m_itemToResource.value(m_listWidget->currentItem());
+ if (!matchAll) {
+ bool searchForNewPathWithContents = true;
+
+ if (!currentPath.isEmpty()) { // if the currentPath is empty we will search for a new path too
+ QMap<QString, bool>::ConstIterator it = pathToMatchingContents.constFind(currentPath);
+ if (it != pathToMatchingContents.constEnd() && it.value()) // the current item has contents, we don't need to search for another path
+ searchForNewPathWithContents = false;
+ }
+
+ if (searchForNewPathWithContents) {
+ // we find the first path with the matching contents
+ QMap<QString, bool>::ConstIterator itContents = pathToMatchingContents.constBegin();
+ while (itContents != pathToMatchingContents.constEnd()) {
+ if (itContents.value()) {
+ newCurrentPath = itContents.key(); // the new path will be activated
+ break;
+ }
+
+ itContents++;
+ }
+ }
+
+ QFileInfo fi(currentResource);
+ if (!fi.fileName().contains(m_filterPattern, Qt::CaseInsensitive)) { // the case when the current resource is filtered out
+ const QStringList fileNames = m_pathToContents.value(newCurrentPath);
+ QStringListIterator it(fileNames);
+ while (it.hasNext()) { // we try to select the first matching resource from the newCurrentPath
+ QString fileName = it.next();
+ if (fileName.contains(m_filterPattern, Qt::CaseInsensitive)) {
+ QDir dirPath(newCurrentPath);
+ currentResource = dirPath.absoluteFilePath(fileName); // the new resource inside newCurrentPath will be activated
+ break;
+ }
+ }
+ }
+ }
+
+ QTreeWidgetItem *newCurrentItem = m_pathToItem.value(newCurrentPath);
+ if (currentPath != newCurrentPath)
+ m_treeWidget->setCurrentItem(newCurrentItem);
+ else
+ slotCurrentPathChanged(newCurrentItem); // trigger filtering on the current path
+
+ QListWidgetItem *currentResourceItem = m_resourceToItem.value(currentResource);
+ if (currentResourceItem) {
+ m_listWidget->setCurrentItem(currentResourceItem);
+ m_listWidget->scrollToItem(currentResourceItem);
+ }
+
+ QMapIterator<QString, bool> it(pathToVisible); // hide all paths filtered out
+ while (it.hasNext()) {
+ const QString path = it.next().key();
+ QTreeWidgetItem *item = m_pathToItem.value(path);
+ if (item)
+ item->setHidden(!it.value());
+ }
+}
+
+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)
+{
+ const bool matchAll = m_filterPattern.isEmpty();
+
+ QDir dir(path);
+ QStringList fileNames = m_pathToContents.value(path);
+ QStringListIterator it(fileNames);
+ while (it.hasNext()) {
+ QString fileName = it.next();
+ const bool showProperty = matchAll || fileName.contains(m_filterPattern, Qt::CaseInsensitive);
+ if (showProperty) {
+ QString filePath = dir.absoluteFilePath(fileName);
+ 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;
+
+ QIcon editIcon = QIcon::fromTheme("document-properties", qdesigner_internal::createIconSet(QLatin1String("edit.png")));
+ d_ptr->m_editResourcesAction = new QAction(editIcon, 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);
+
+ QIcon refreshIcon = QIcon::fromTheme("view-refresh", qdesigner_internal::createIconSet(QLatin1String("reload.png")));
+ d_ptr->m_reloadResourcesAction = new QAction(refreshIcon, 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);
+
+ QIcon copyIcon = QIcon::fromTheme("edit-copy", qdesigner_internal::createIconSet(QLatin1String("editcopy.png")));
+ d_ptr->m_copyResourcePathAction = new QAction(copyIcon, tr("Copy Path"), this);
+ connect(d_ptr->m_copyResourcePathAction, SIGNAL(triggered()), this, SLOT(slotCopyResourcePath()));
+ d_ptr->m_copyResourcePathAction->setEnabled(false);
+
+ //d_ptr->m_filterWidget = new qdesigner_internal::FilterWidget(0, qdesigner_internal::FilterWidget::LayoutAlignNone);
+ d_ptr->m_filterWidget = new qdesigner_internal::FilterWidget(d_ptr->m_toolBar);
+ d_ptr->m_toolBar->addWidget(d_ptr->m_filterWidget);
+ connect(d_ptr->m_filterWidget, SIGNAL(filterChanged(QString)), this, SLOT(slotFilterChanged(QString)));
+
+ 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();
+}
+
+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)
+{
+ if (resource.isEmpty())
+ return;
+ 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();
+}
+
+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/src/designer/src/lib/shared/qtresourceview_p.h b/src/designer/src/lib/shared/qtresourceview_p.h
new file mode 100644
index 000000000..947df64e4
--- /dev/null
+++ b/src/designer/src/lib/shared/qtresourceview_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit 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:
+
+ QScopedPointer<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))
+ Q_PRIVATE_SLOT(d_func(), void slotFilterChanged(const QString &pattern))
+};
+
+class QDESIGNER_SHARED_EXPORT QtResourceViewDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit QtResourceViewDialog(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ virtual ~QtResourceViewDialog();
+
+ QString selectedResource() const;
+ void selectResource(const QString &path);
+
+ bool isResourceEditingEnabled() const;
+ void setResourceEditingEnabled(bool enable);
+
+private:
+ QScopedPointer<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/src/designer/src/lib/shared/richtexteditor.cpp b/src/designer/src/lib/shared/richtexteditor.cpp
new file mode 100644
index 000000000..c2cdb2098
--- /dev/null
+++ b/src/designer/src/lib/shared/richtexteditor.cpp
@@ -0,0 +1,906 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QXmlStreamAttributes>
+
+#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 RichTextDialogGroupC[] = "RichTextDialog";
+static const char GeometryKeyC[] = "Geometry";
+static const char TabKeyC[] = "Tab";
+
+const bool simplifyRichTextDefault = true;
+
+namespace qdesigner_internal {
+
+// Richtext simplification filter helpers: Elements to be discarded
+static inline bool filterElement(const QStringRef &name)
+{
+ return name != QLatin1String("meta") && name != QLatin1String("style");
+}
+
+// Richtext simplification filter helpers: Filter attributes of elements
+static inline void filterAttributes(const QStringRef &name,
+ QXmlStreamAttributes *atts,
+ bool *paragraphAlignmentFound)
+{
+ typedef QXmlStreamAttributes::iterator AttributeIt;
+
+ if (atts->isEmpty())
+ return;
+
+ // No style attributes for <body>
+ if (name == QLatin1String("body")) {
+ atts->clear();
+ return;
+ }
+
+ // Clean out everything except 'align' for 'p'
+ if (name == QLatin1String("p")) {
+ for (AttributeIt it = atts->begin(); it != atts->end(); ) {
+ if (it->name() == QLatin1String("align")) {
+ ++it;
+ *paragraphAlignmentFound = true;
+ } else {
+ it = atts->erase(it);
+ }
+ }
+ return;
+ }
+}
+
+// Richtext simplification filter helpers: Check for blank QStringRef.
+static inline bool isWhiteSpace(const QStringRef &in)
+{
+ const int count = in.size();
+ for (int i = 0; i < count; i++)
+ if (!in.at(i).isSpace())
+ return false;
+ return true;
+}
+
+// Richtext simplification filter: Remove hard-coded font settings,
+// <style> elements, <p> attributes other than 'align' and
+// and unnecessary meta-information.
+QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr = 0)
+{
+ unsigned elementCount = 0;
+ bool paragraphAlignmentFound = false;
+ QString out;
+ QXmlStreamReader reader(in);
+ QXmlStreamWriter writer(&out);
+ writer.setAutoFormatting(false);
+ writer.setAutoFormattingIndent(0);
+
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement:
+ elementCount++;
+ if (filterElement(reader.name())) {
+ const QStringRef name = reader.name();
+ QXmlStreamAttributes attributes = reader.attributes();
+ filterAttributes(name, &attributes, &paragraphAlignmentFound);
+ writer.writeStartElement(name.toString());
+ if (!attributes.isEmpty())
+ writer.writeAttributes(attributes);
+ } else {
+ reader.readElementText(); // Skip away all nested elements and characters.
+ }
+ break;
+ case QXmlStreamReader::Characters:
+ if (!isWhiteSpace(reader.text()))
+ writer.writeCharacters(reader.text().toString());
+ break;
+ case QXmlStreamReader::EndElement:
+ writer.writeEndElement();
+ break;
+ default:
+ break;
+ }
+ }
+ // Check for plain text (no spans, just <html><head><body><p>)
+ if (isPlainTextPtr)
+ *isPlainTextPtr = !paragraphAlignmentFound && elementCount == 4u; //
+ return out;
+}
+
+class RichTextEditor : public QTextEdit
+{
+ Q_OBJECT
+public:
+ explicit RichTextEditor(QWidget *parent = 0);
+ void setDefaultFont(QFont font);
+
+ QToolBar *createToolBar(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+ bool simplifyRichText() const { return m_simplifyRichText; }
+
+public slots:
+ void setFontBold(bool b);
+ void setFontPointSize(double);
+ void setText(const QString &text);
+ void setSimplifyRichText(bool v);
+ QString text(Qt::TextFormat format) const;
+
+signals:
+ void stateChanged();
+ void simplifyRichTextChanged(bool);
+
+private:
+ bool m_simplifyRichText;
+};
+
+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;
+ QAction *m_simplify_richtext_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);
+
+ addSeparator();
+
+ // Simplify rich text
+ m_simplify_richtext_action
+ = createCheckableAction(createIconSet(QLatin1String("simplifyrichtext.png")),
+ tr("Simplify Rich Text"), m_editor, SLOT(setSimplifyRichText(bool)));
+ m_simplify_richtext_action->setChecked(m_editor->simplifyRichText());
+ connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)),
+ m_simplify_richtext_action, SLOT(setChecked(bool)));
+ addAction(m_simplify_richtext_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), m_simplifyRichText(simplifyRichTextDefault)
+{
+ 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::setSimplifyRichText(bool v)
+{
+ if (v != m_simplifyRichText) {
+ m_simplifyRichText = v;
+ emit simplifyRichTextChanged(v);
+ }
+}
+
+void RichTextEditor::setDefaultFont(QFont font)
+{
+ // Some default fonts on Windows have a default size of 7.8,
+ // which results in complicated rich text generated by toHtml().
+ // Use an integer value.
+ const int pointSize = qRound(font.pointSizeF());
+ if (pointSize > 0 && !qFuzzyCompare(qreal(pointSize), font.pointSizeF())) {
+ font.setPointSize(pointSize);
+ }
+
+ 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 m_simplifyRichText ? simplifyRichTextFilter(toHtml()) : toHtml();
+ case Qt::AutoText:
+ break;
+ }
+ const QString html = toHtml();
+ bool isPlainText;
+ const QString simplifiedHtml = simplifyRichTextFilter(html, &isPlainText);
+ if (isPlainText)
+ return toPlainText();
+ return m_simplifyRichText ? simplifiedHtml : 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),
+ m_initialTab(RichTextIndex)
+{
+ setWindowTitle(tr("Edit text"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ // Read settings
+ const QDesignerSettingsInterface *settings = core->settingsManager();
+ const QString rootKey = QLatin1String(RichTextDialogGroupC) + QLatin1Char('/');
+ const QByteArray lastGeometry = settings->value(rootKey + QLatin1String(GeometryKeyC)).toByteArray();
+ const int initialTab = settings->value(rootKey + QLatin1String(TabKeyC), QVariant(m_initialTab)).toInt();
+ if (initialTab == RichTextIndex || initialTab == SourceIndex)
+ m_initialTab = initialTab;
+
+ m_text_edit->setAcceptRichText(false);
+ new HtmlHighlighter(m_text_edit);
+
+ connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged()));
+ connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), 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);
+
+ if (!lastGeometry.isEmpty())
+ restoreGeometry(lastGeometry);
+}
+
+RichTextEditorDialog::~RichTextEditorDialog()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(RichTextDialogGroupC));
+
+ settings->setValue(QLatin1String(GeometryKeyC), saveGeometry());
+ settings->setValue(QLatin1String(TabKeyC), m_tab_widget->currentIndex());
+ settings->endGroup();
+}
+
+int RichTextEditorDialog::showDialog()
+{
+ m_tab_widget->setCurrentIndex(m_initialTab);
+ switch (m_initialTab) {
+ case RichTextIndex:
+ m_editor->selectAll();
+ m_editor->setFocus();
+ break;
+ case SourceIndex:
+ m_text_edit->selectAll();
+ m_text_edit->setFocus();
+ break;
+ }
+ return exec();
+}
+
+void RichTextEditorDialog::setDefaultFont(const QFont &font)
+{
+ m_editor->setDefaultFont(font);
+}
+
+void RichTextEditorDialog::setText(const QString &text)
+{
+ // Generally simplify rich text unless verbose text is found.
+ const bool isSimplifiedRichText = !text.startsWith("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">");
+ m_editor->setSimplifyRichText(isSimplifiedRichText);
+ 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/src/designer/src/lib/shared/richtexteditor_p.h b/src/designer/src/lib/shared/richtexteditor_p.h
new file mode 100644
index 000000000..086c5d518
--- /dev/null
+++ b/src/designer/src/lib/shared/richtexteditor_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit 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;
+ int m_initialTab;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // RITCHTEXTEDITOR_H
diff --git a/src/designer/src/lib/shared/scriptcommand.cpp b/src/designer/src/lib/shared/scriptcommand.cpp
new file mode 100644
index 000000000..a8f47a574
--- /dev/null
+++ b/src/designer/src/lib/shared/scriptcommand.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/scriptcommand_p.h b/src/designer/src/lib/shared/scriptcommand_p.h
new file mode 100644
index 000000000..eed8e06eb
--- /dev/null
+++ b/src/designer/src/lib/shared/scriptcommand_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/scriptdialog.cpp b/src/designer/src/lib/shared/scriptdialog.cpp
new file mode 100644
index 000000000..e2c1c7460
--- /dev/null
+++ b/src/designer/src/lib/shared/scriptdialog.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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>
+#ifdef QT_SCRIPT_LIB
+#include <QtScript/QScriptEngine>
+#endif
+
+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;
+#ifdef QT_SCRIPT_LIB
+ QScriptEngine scriptEngine;
+ if (scriptEngine.canEvaluate(script))
+ return true;
+ m_dialogGui->message(this, QDesignerDialogGuiInterface::ScriptDialogMessage, QMessageBox::Warning,
+ windowTitle(), tr("Syntax error"), QMessageBox::Ok);
+ return false;
+#else
+ return true;
+#endif
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/scriptdialog_p.h b/src/designer/src/lib/shared/scriptdialog_p.h
new file mode 100644
index 000000000..bb1881d00
--- /dev/null
+++ b/src/designer/src/lib/shared/scriptdialog_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/scripterrordialog.cpp b/src/designer/src/lib/shared/scripterrordialog.cpp
new file mode 100644
index 000000000..30d57342b
--- /dev/null
+++ b/src/designer/src/lib/shared/scripterrordialog.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/scripterrordialog_p.h b/src/designer/src/lib/shared/scripterrordialog_p.h
new file mode 100644
index 000000000..24ead6f4b
--- /dev/null
+++ b/src/designer/src/lib/shared/scripterrordialog_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/selectsignaldialog.ui b/src/designer/src/lib/shared/selectsignaldialog.ui
new file mode 100644
index 000000000..99387dd2a
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/shared.pri b/src/designer/src/lib/shared/shared.pri
new file mode 100644
index 000000000..9d5091164
--- /dev/null
+++ b/src/designer/src/lib/shared/shared.pri
@@ -0,0 +1,189 @@
+
+INCLUDEPATH += $$PWD
+contains(QT_CONFIG, script): QT += script
+
+include(../../../../shared/qtpropertybrowser/qtpropertybrowserutils.pri)
+include(../../../../shared/deviceskin/deviceskin.pri)
+include(../../../../../src/tools/rcc/rcc.pri)
+include(../../../../shared/findwidget/findwidget.pri)
+include(../../../../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/src/designer/src/lib/shared/shared.qrc b/src/designer/src/lib/shared/shared.qrc
new file mode 100644
index 000000000..81be8076d
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/shared_enums_p.h b/src/designer/src/lib/shared/shared_enums_p.h
new file mode 100644
index 000000000..cbf90589d
--- /dev/null
+++ b/src/designer/src/lib/shared/shared_enums_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/shared_global_p.h b/src/designer/src/lib/shared/shared_global_p.h
new file mode 100644
index 000000000..ce0a7aaf4
--- /dev/null
+++ b/src/designer/src/lib/shared/shared_global_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/shared_settings.cpp b/src/designer/src/lib/shared/shared_settings.cpp
new file mode 100644
index 000000000..20b49fd35
--- /dev/null
+++ b/src/designer/src/lib/shared/shared_settings.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 (const 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/src/designer/src/lib/shared/shared_settings_p.h b/src/designer/src/lib/shared/shared_settings_p.h
new file mode 100644
index 000000000..6e151ee53
--- /dev/null
+++ b/src/designer/src/lib/shared/shared_settings_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/sheet_delegate.cpp b/src/designer/src/lib/shared/sheet_delegate.cpp
new file mode 100644
index 000000000..896ed5b83
--- /dev/null
+++ b/src/designer/src/lib/shared/sheet_delegate.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/sheet_delegate_p.h b/src/designer/src/lib/shared/sheet_delegate_p.h
new file mode 100644
index 000000000..887cc6619
--- /dev/null
+++ b/src/designer/src/lib/shared/sheet_delegate_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/signalslotdialog.cpp b/src/designer/src/lib/shared/signalslotdialog.cpp
new file mode 100644
index 000000000..a65aafade
--- /dev/null
+++ b/src/designer/src/lib/shared/signalslotdialog.cpp
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/signalslotdialog.ui b/src/designer/src/lib/shared/signalslotdialog.ui
new file mode 100644
index 000000000..1a8a8d921
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/signalslotdialog_p.h b/src/designer/src/lib/shared/signalslotdialog_p.h
new file mode 100644
index 000000000..1bfeecece
--- /dev/null
+++ b/src/designer/src/lib/shared/signalslotdialog_p.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/spacer_widget.cpp b/src/designer/src/lib/shared/spacer_widget.cpp
new file mode 100644
index 000000000..528a4f427
--- /dev/null
+++ b/src/designer/src/lib/shared/spacer_widget.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/lib/shared/spacer_widget_p.h b/src/designer/src/lib/shared/spacer_widget_p.h
new file mode 100644
index 000000000..dd9288d24
--- /dev/null
+++ b/src/designer/src/lib/shared/spacer_widget_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/stylesheeteditor.cpp b/src/designer/src/lib/shared/stylesheeteditor.cpp
new file mode 100644
index 000000000..ee5fea41e
--- /dev/null
+++ b/src/designer/src/lib/shared/stylesheeteditor.cpp
@@ -0,0 +1,409 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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);
+ setAcceptRichText(false);
+ 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(QPoint)),
+ this, SLOT(slotContextMenuRequested(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)
+{
+ const QColor color = QColorDialog::getColor(0xffffffff, this, QString(), QColorDialog::ShowAlphaChannel);
+ if (!color.isValid())
+ return;
+
+ 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 = qvariant_cast<PropertySheetStringValue>(sheet->property(index));
+ setText(value.value());
+}
+
+void StyleSheetPropertyEditorDialog::applyStyleSheet()
+{
+ const PropertySheetStringValue value(text(), false);
+ m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), QVariant::fromValue(value));
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/lib/shared/stylesheeteditor_p.h b/src/designer/src/lib/shared/stylesheeteditor_p.h
new file mode 100644
index 000000000..ce735c71b
--- /dev/null
+++ b/src/designer/src/lib/shared/stylesheeteditor_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui b/src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 000000000..7ff64b0cb
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui b/src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui
new file mode 100644
index 000000000..203af78ff
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui b/src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 000000000..0ac856e4e
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui b/src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui
new file mode 100644
index 000000000..52f0f66a4
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui b/src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 000000000..0d219c937
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui b/src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui
new file mode 100644
index 000000000..c82a78e87
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui b/src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 000000000..adc5d4847
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui b/src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui
new file mode 100644
index 000000000..defb42a40
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui b/src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 000000000..18d31ab91
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui b/src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui
new file mode 100644
index 000000000..703d594f4
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui b/src/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui
new file mode 100644
index 000000000..1be629818
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/Main_Window.ui b/src/designer/src/lib/shared/templates/forms/Main_Window.ui
new file mode 100644
index 000000000..9ae3b5024
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/templates/forms/Widget.ui b/src/designer/src/lib/shared/templates/forms/Widget.ui
new file mode 100644
index 000000000..4b7d6a45f
--- /dev/null
+++ b/src/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/src/designer/src/lib/shared/textpropertyeditor.cpp b/src/designer/src/lib/shared/textpropertyeditor.cpp
new file mode 100644
index 000000000..bc6cbeac7
--- /dev/null
+++ b/src/designer/src/lib/shared/textpropertyeditor.cpp
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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://qt.nokia.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);
+ setText(m_cachedText);
+ 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/src/designer/src/lib/shared/textpropertyeditor_p.h b/src/designer/src/lib/shared/textpropertyeditor_p.h
new file mode 100644
index 000000000..da92e8e82
--- /dev/null
+++ b/src/designer/src/lib/shared/textpropertyeditor_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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
+ };
+
+ explicit 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/src/designer/src/lib/shared/widgetdatabase.cpp b/src/designer/src/lib/shared/widgetdatabase.cpp
new file mode 100644
index 000000000..aa1a77592
--- /dev/null
+++ b/src/designer/src/lib/shared/widgetdatabase.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/QScopedPointer>
+#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();
+ QScopedPointer<DomUI> domUI(QDesignerWidgetBox::xmlToUi(className, widget.domXml(), false));
+ if (domUI.isNull())
+ return QString();
+ domUI->setAttributeVersion(QLatin1String("4.0"));
+ 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();
+ }
+ 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/src/designer/src/lib/shared/widgetdatabase_p.h b/src/designer/src/lib/shared/widgetdatabase_p.h
new file mode 100644
index 000000000..eb89cb139
--- /dev/null
+++ b/src/designer/src/lib/shared/widgetdatabase_p.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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:
+ explicit 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:
+ explicit 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/src/designer/src/lib/shared/widgetfactory.cpp b/src/designer/src/lib/shared/widgetfactory.cpp
new file mode 100644
index 000000000..bcd23eed3
--- /dev/null
+++ b/src/designer/src/lib/shared/widgetfactory.cpp
@@ -0,0 +1,899 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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;
+ }
+ if (QWidget *promotedWidget = createWidget(baseClass, parentWidget)) {
+ promoteWidget(core(), promotedWidget, widgetName);
+ return promotedWidget; // Do not initialize twice.
+ }
+ } 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)
+{
+ if (!style)
+ return;
+ const QPalette standardPalette = style->standardPalette();
+ if (widget->style() == style && widget->palette() == standardPalette)
+ return;
+
+ widget->setStyle(style);
+ widget->setPalette(standardPalette);
+ const QWidgetList lst = widget->findChildren<QWidget*>();
+ 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;
+#ifndef QT_NO_SIZEGRIP
+ } else if (qobject_cast<QSizeGrip*>(widget)) {
+ return (m_lastWasAPassiveInteractor = true);
+#endif
+ } 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/src/designer/src/lib/shared/widgetfactory_p.h b/src/designer/src/lib/shared/widgetfactory_p.h
new file mode 100644
index 000000000..994731c41
--- /dev/null
+++ b/src/designer/src/lib/shared/widgetfactory_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/lib/shared/zoomwidget.cpp b/src/designer/src/lib/shared/zoomwidget.cpp
new file mode 100644
index 000000000..c77a518fe
--- /dev/null
+++ b/src/designer/src/lib/shared/zoomwidget.cpp
@@ -0,0 +1,570 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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_zoomMenu(0)
+{
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ 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);
+}
+
+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;
+}
+
+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 = w->findChild<QObject*>(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() << '>' << Q_FUNC_INFO << 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());
+ setSceneRect(QRectF(QPointF(0, 0), widgetSizeF));
+ scrollToOrigin();
+ m_widgetResizeBlocked = false;
+ if (debugZoomWidget > 1)
+ qDebug() << '<' << Q_FUNC_INFO << widgetSizeF << m_proxy->widget()->size() << m_proxy->size();
+ }
+}
+
+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::dump " << 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/src/designer/src/lib/shared/zoomwidget_p.h b/src/designer/src/lib/shared/zoomwidget_p.h
new file mode 100644
index 000000000..4b2a05077
--- /dev/null
+++ b/src/designer/src/lib/shared/zoomwidget_p.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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_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);
+
+ 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_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/src/designer/src/plugins/activeqt/activeqt.pro b/src/designer/src/plugins/activeqt/activeqt.pro
new file mode 100644
index 000000000..f58df8a38
--- /dev/null
+++ b/src/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/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp b/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp
new file mode 100644
index 000000000..f58e1856d
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.h b/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.h
new file mode 100644
index 000000000..cb94eea6c
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetextrainfo.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/activeqt/qaxwidgetplugin.cpp b/src/designer/src/plugins/activeqt/qaxwidgetplugin.cpp
new file mode 100644
index 000000000..019ada2f5
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetplugin.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/activeqt/qaxwidgetplugin.h b/src/designer/src/plugins/activeqt/qaxwidgetplugin.h
new file mode 100644
index 000000000..a018811e6
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetplugin.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp b/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp
new file mode 100644
index 000000000..7d8408e12
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h b/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h
new file mode 100644
index 000000000..b1fd35b54
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp b/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp
new file mode 100644
index 000000000..d49f369d3
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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::fromWCharArray(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/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.h b/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.h
new file mode 100644
index 000000000..aec27765e
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qaxwidgettaskmenu.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/activeqt/qdesigneraxwidget.cpp b/src/designer/src/plugins/activeqt/qdesigneraxwidget.cpp
new file mode 100644
index 000000000..cadbc1dd6
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qdesigneraxwidget.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/activeqt/qdesigneraxwidget.h b/src/designer/src/plugins/activeqt/qdesigneraxwidget.h
new file mode 100644
index 000000000..88d49e1b0
--- /dev/null
+++ b/src/designer/src/plugins/activeqt/qdesigneraxwidget.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 overridden
+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/src/designer/src/plugins/phononwidgets/images/seekslider.png b/src/designer/src/plugins/phononwidgets/images/seekslider.png
new file mode 100644
index 000000000..a1f4cb0d5
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/images/seekslider.png
Binary files differ
diff --git a/src/designer/src/plugins/phononwidgets/images/videoplayer.png b/src/designer/src/plugins/phononwidgets/images/videoplayer.png
new file mode 100644
index 000000000..55d86a6d3
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/images/videoplayer.png
Binary files differ
diff --git a/src/designer/src/plugins/phononwidgets/images/videowidget.png b/src/designer/src/plugins/phononwidgets/images/videowidget.png
new file mode 100644
index 000000000..3e8706e45
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/images/videowidget.png
Binary files differ
diff --git a/src/designer/src/plugins/phononwidgets/images/volumeslider.png b/src/designer/src/plugins/phononwidgets/images/volumeslider.png
new file mode 100644
index 000000000..ea81dd2a1
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/images/volumeslider.png
Binary files differ
diff --git a/src/designer/src/plugins/phononwidgets/phononcollection.cpp b/src/designer/src/plugins/phononwidgets/phononcollection.cpp
new file mode 100644
index 000000000..c26571434
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/phononcollection.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/phononwidgets/phononwidgets.pro b/src/designer/src/plugins/phononwidgets/phononwidgets.pro
new file mode 100644
index 000000000..4e0f0cc1a
--- /dev/null
+++ b/src/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/src/designer/src/plugins/phononwidgets/phononwidgets.qrc b/src/designer/src/plugins/phononwidgets/phononwidgets.qrc
new file mode 100644
index 000000000..aa51330fd
--- /dev/null
+++ b/src/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/src/designer/src/plugins/phononwidgets/seeksliderplugin.cpp b/src/designer/src/plugins/phononwidgets/seeksliderplugin.cpp
new file mode 100644
index 000000000..23f479096
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/seeksliderplugin.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 tr(toolTipC);
+}
+
+QString SeekSliderPlugin::whatsThis() const
+{
+ return tr(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/src/designer/src/plugins/phononwidgets/seeksliderplugin.h b/src/designer/src/plugins/phononwidgets/seeksliderplugin.h
new file mode 100644
index 000000000..516ba73d1
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/seeksliderplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/phononwidgets/videoplayerplugin.cpp b/src/designer/src/plugins/phononwidgets/videoplayerplugin.cpp
new file mode 100644
index 000000000..129ad1694
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/videoplayerplugin.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 tr(toolTipC);
+}
+
+QString VideoPlayerPlugin::whatsThis() const
+{
+ return tr(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/src/designer/src/plugins/phononwidgets/videoplayerplugin.h b/src/designer/src/plugins/phononwidgets/videoplayerplugin.h
new file mode 100644
index 000000000..3d7c1b31c
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/videoplayerplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp b/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp
new file mode 100644
index 000000000..90cc96ffa
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.h b/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.h
new file mode 100644
index 000000000..a94061186
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/videoplayertaskmenu.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOPLAYERTASKMENU_H
+#define VIDEOPLAYERTASKMENU_H
+
+
+#include <QtCore/QObject>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/private/extensionfactory_p.h>
+
+#include <phonon/backendcapabilities.h>
+#include <phonon/videoplayer.h>
+
+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/src/designer/src/plugins/phononwidgets/volumesliderplugin.cpp b/src/designer/src/plugins/phononwidgets/volumesliderplugin.cpp
new file mode 100644
index 000000000..bff21b61f
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/volumesliderplugin.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 tr(toolTipC);
+}
+
+QString VolumeSliderPlugin::whatsThis() const
+{
+ return tr(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/src/designer/src/plugins/phononwidgets/volumesliderplugin.h b/src/designer/src/plugins/phononwidgets/volumesliderplugin.h
new file mode 100644
index 000000000..005215e62
--- /dev/null
+++ b/src/designer/src/plugins/phononwidgets/volumesliderplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/plugins.pri b/src/designer/src/plugins/plugins.pri
new file mode 100644
index 000000000..e5edfe2f2
--- /dev/null
+++ b/src/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/src/designer/src/plugins/plugins.pro b/src/designer/src/plugins/plugins.pro
new file mode 100644
index 000000000..bcebb82ec
--- /dev/null
+++ b/src/designer/src/plugins/plugins.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+REQUIRES = !CONFIG(static,shared|static)
+contains(QT_CONFIG, qt3support): SUBDIRS += widgets
+win32: SUBDIRS += activeqt
+# contains(QT_CONFIG, opengl): SUBDIRS += tools/view3d
+contains(QT_CONFIG, webkit): SUBDIRS += qwebview
+contains(QT_CONFIG, phonon): SUBDIRS += phononwidgets
+contains(QT_CONFIG, declarative): SUBDIRS += qdeclarativeview
diff --git a/src/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro
new file mode 100644
index 000000000..b8abe8741
--- /dev/null
+++ b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+TARGET = qdeclarativeview
+CONFIG += qt warn_on plugin designer
+QT += declarative
+
+include(../plugins.pri)
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+SOURCES += qdeclarativeview_plugin.cpp
+HEADERS += qdeclarativeview_plugin.h
diff --git a/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp
new file mode 100644
index 000000000..99dac8aa9
--- /dev/null
+++ b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeview_plugin.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtDeclarative/QDeclarativeView>
+
+static const char toolTipC[] = "QtDeclarative view widget";
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeViewPlugin::QDeclarativeViewPlugin(QObject *parent) :
+ QObject(parent),
+ m_initialized(false)
+{
+}
+
+QString QDeclarativeViewPlugin::name() const
+{
+ return QLatin1String("QDeclarativeView");
+}
+
+QString QDeclarativeViewPlugin::group() const
+{
+ return QLatin1String("Display Widgets");
+}
+
+QString QDeclarativeViewPlugin::toolTip() const
+{
+ return tr(toolTipC);
+}
+
+QString QDeclarativeViewPlugin::whatsThis() const
+{
+ return tr(toolTipC);
+}
+
+QString QDeclarativeViewPlugin::includeFile() const
+{
+ return QLatin1String("QtDeclarative/QDeclarativeView");
+}
+
+QIcon QDeclarativeViewPlugin::icon() const
+{
+ return QIcon();
+}
+
+bool QDeclarativeViewPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *QDeclarativeViewPlugin::createWidget(QWidget *parent)
+{
+ return new QDeclarativeView(parent);
+}
+
+bool QDeclarativeViewPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void QDeclarativeViewPlugin::initialize(QDesignerFormEditorInterface * /*core*/)
+{
+ if (m_initialized)
+ return;
+
+ m_initialized = true;
+}
+
+QString QDeclarativeViewPlugin::domXml() const
+{
+ return QLatin1String("\
+ <ui language=\"c++\">\
+ <widget class=\"QDeclarativeView\" name=\"declarativeView\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>300</width>\
+ <height>200</height>\
+ </rect>\
+ </property>\
+ </widget>\
+ </ui>");
+}
+
+Q_EXPORT_PLUGIN2(customwidgetplugin, QDeclarativeViewPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h
new file mode 100644
index 000000000..0f14df74f
--- /dev/null
+++ b/src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEW_PLUGIN_H
+#define QDECLARATIVEVIEW_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeViewPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ QDeclarativeViewPlugin(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 // QDECLARATIVEVIEW_PLUGIN_H
diff --git a/src/designer/src/plugins/qwebview/images/qwebview.png b/src/designer/src/plugins/qwebview/images/qwebview.png
new file mode 100644
index 000000000..01a0920c9
--- /dev/null
+++ b/src/designer/src/plugins/qwebview/images/qwebview.png
Binary files differ
diff --git a/src/designer/src/plugins/qwebview/qwebview.pro b/src/designer/src/plugins/qwebview/qwebview.pro
new file mode 100644
index 000000000..b1f6371d1
--- /dev/null
+++ b/src/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/src/designer/src/plugins/qwebview/qwebview_plugin.cpp b/src/designer/src/plugins/qwebview/qwebview_plugin.cpp
new file mode 100644
index 000000000..9c965f0ca
--- /dev/null
+++ b/src/designer/src/plugins/qwebview/qwebview_plugin.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 tr(toolTipC);
+}
+
+QString QWebViewPlugin::whatsThis() const
+{
+ return tr(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/src/designer/src/plugins/qwebview/qwebview_plugin.h b/src/designer/src/plugins/qwebview/qwebview_plugin.h
new file mode 100644
index 000000000..d364bc1a4
--- /dev/null
+++ b/src/designer/src/plugins/qwebview/qwebview_plugin.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/qwebview/qwebview_plugin.qrc b/src/designer/src/plugins/qwebview/qwebview_plugin.qrc
new file mode 100644
index 000000000..a3e2b9016
--- /dev/null
+++ b/src/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/src/designer/src/plugins/tools/view3d/view3d.cpp b/src/designer/src/plugins/tools/view3d/view3d.cpp
new file mode 100644
index 000000000..06718f433
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d.cpp
@@ -0,0 +1,492 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#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/src/designer/src/plugins/tools/view3d/view3d.h b/src/designer/src/plugins/tools/view3d/view3d.h
new file mode 100644
index 000000000..43e2ae9eb
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/tools/view3d/view3d.pro b/src/designer/src/plugins/tools/view3d/view3d.pro
new file mode 100644
index 000000000..c28c70693
--- /dev/null
+++ b/src/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/src/designer/src/plugins/tools/view3d/view3d_global.h b/src/designer/src/plugins/tools/view3d/view3d_global.h
new file mode 100644
index 000000000..5eb936ab4
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/tools/view3d/view3d_plugin.cpp b/src/designer/src/plugins/tools/view3d/view3d_plugin.cpp
new file mode 100644
index 000000000..62b7868e7
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d_plugin.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/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/src/designer/src/plugins/tools/view3d/view3d_plugin.h b/src/designer/src/plugins/tools/view3d/view3d_plugin.h
new file mode 100644
index 000000000..6845bb30a
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d_plugin.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/tools/view3d/view3d_tool.cpp b/src/designer/src/plugins/tools/view3d/view3d_tool.cpp
new file mode 100644
index 000000000..e92a58bc9
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d_tool.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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/src/designer/src/plugins/tools/view3d/view3d_tool.h b/src/designer/src/plugins/tools/view3d/view3d_tool.h
new file mode 100644
index 000000000..acb4dc1b6
--- /dev/null
+++ b/src/designer/src/plugins/tools/view3d/view3d_tool.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp b/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp
new file mode 100644
index 000000000..35c8e32c3
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h b/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h
new file mode 100644
index 000000000..bcd823b86
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp b/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp
new file mode 100644
index 000000000..0ed5b88db
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h b/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h
new file mode 100644
index 000000000..9074b38f6
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp b/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp
new file mode 100644
index 000000000..6cd037247
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h b/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h
new file mode 100644
index 000000000..48b844141
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp b/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp
new file mode 100644
index 000000000..331b48964
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h b/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h
new file mode 100644
index 000000000..d1c99d07f
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp b/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp
new file mode 100644
index 000000000..2dda71749
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h b/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h
new file mode 100644
index 000000000..caedc133f
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp b/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp
new file mode 100644
index 000000000..4c5b193bd
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.h b/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.h
new file mode 100644
index 000000000..e006d7344
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3listview/q3listview_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp
new file mode 100644
index 000000000..b156623b3
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h
new file mode 100644
index 000000000..fdadee61a
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp
new file mode 100644
index 000000000..9c91586a7
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h
new file mode 100644
index 000000000..00a1c205f
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp b/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp
new file mode 100644
index 000000000..3305e2b74
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.h b/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.h
new file mode 100644
index 000000000..3b5ab9f4b
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3table/q3table_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3table/q3table_plugin.cpp b/src/designer/src/plugins/widgets/q3table/q3table_plugin.cpp
new file mode 100644
index 000000000..38562a210
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3table/q3table_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3table/q3table_plugin.h b/src/designer/src/plugins/widgets/q3table/q3table_plugin.h
new file mode 100644
index 000000000..92034ea59
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3table/q3table_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp b/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp
new file mode 100644
index 000000000..3c1530a56
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h b/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h
new file mode 100644
index 000000000..5fe89097e
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp b/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp
new file mode 100644
index 000000000..8da4315cb
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h b/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h
new file mode 100644
index 000000000..cfae30832
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp
new file mode 100644
index 000000000..44d5286b6
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h
new file mode 100644
index 000000000..d5865c84f
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp
new file mode 100644
index 000000000..83ef66bd8
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h
new file mode 100644
index 000000000..344f3e27c
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp b/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp
new file mode 100644
index 000000000..2f8cca257
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h b/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h
new file mode 100644
index 000000000..2ba00f027
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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:
+ explicit 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/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp
new file mode 100644
index 000000000..500185da5
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h
new file mode 100644
index 000000000..9c6324de0
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp
new file mode 100644
index 000000000..2fa87cc09
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h
new file mode 100644
index 000000000..0e319c259
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp b/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp
new file mode 100644
index 000000000..a6bc34844
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h b/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h
new file mode 100644
index 000000000..53f90299f
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of 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/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp b/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp
new file mode 100644
index 000000000..98cbdc7c7
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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(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/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.h b/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.h
new file mode 100644
index 000000000..fa9138326
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3wizard/q3wizard_container.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit Q3WizardHelper(Q3Wizard *wizard);
+private slots:
+ void slotCurrentChanged();
+private:
+ Q3Wizard *m_wizard;
+};
+
+class Q3WizardExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ explicit 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/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp b/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp
new file mode 100644
index 000000000..bb2c17203
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h b/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h
new file mode 100644
index 000000000..67b958dbb
--- /dev/null
+++ b/src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ explicit 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/src/designer/src/plugins/widgets/qt3supportwidgets.cpp b/src/designer/src/plugins/widgets/qt3supportwidgets.cpp
new file mode 100644
index 000000000..153392787
--- /dev/null
+++ b/src/designer/src/plugins/widgets/qt3supportwidgets.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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/src/designer/src/plugins/widgets/widgets.pro b/src/designer/src/plugins/widgets/widgets.pro
new file mode 100644
index 000000000..4d8f9bae8
--- /dev/null
+++ b/src/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/src/designer/src/sharedcomponents.pri b/src/designer/src/sharedcomponents.pri
new file mode 100644
index 000000000..98c59667d
--- /dev/null
+++ b/src/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/src/designer/src/src.pro b/src/designer/src/src.pro
new file mode 100644
index 000000000..78665b751
--- /dev/null
+++ b/src/designer/src/src.pro
@@ -0,0 +1,12 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS = \
+ uitools \
+ lib \
+ components \
+ designer
+
+CONFIG(shared,shared|static):SUBDIRS += plugins
+
+symbian|wince*: SUBDIRS = uitools