summaryrefslogtreecommitdiffstats
path: root/src/designer/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/designer/src/components')
-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
377 files changed, 44946 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