summaryrefslogtreecommitdiffstats
path: root/src/designer/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/designer/src')
-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
775 files changed, 132028 insertions, 0 deletions
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