OSDN Git Service

add Designer back
authorIvailo Monev <xakepa10@gmail.com>
Sat, 5 Mar 2016 22:04:34 +0000 (22:04 +0000)
committerIvailo Monev <xakepa10@gmail.com>
Sat, 5 Mar 2016 22:04:34 +0000 (22:04 +0000)
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
444 files changed:
README
mkspecs/mkspecs.cmake
src/designer/CMakeLists.txt
src/designer/components/CMakeLists.txt [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor.cmake [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor.cpp [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor.h [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_global.h [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_instance.cpp [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_plugin.cpp [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_plugin.h [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_tool.cpp [new file with mode: 0644]
src/designer/components/buddyeditor/buddyeditor_tool.h [new file with mode: 0644]
src/designer/components/formeditor/brushmanagerproxy.cpp [new file with mode: 0644]
src/designer/components/formeditor/brushmanagerproxy.h [new file with mode: 0644]
src/designer/components/formeditor/default_actionprovider.cpp [new file with mode: 0644]
src/designer/components/formeditor/default_actionprovider.h [new file with mode: 0644]
src/designer/components/formeditor/default_container.cpp [new file with mode: 0644]
src/designer/components/formeditor/default_container.h [new file with mode: 0644]
src/designer/components/formeditor/default_layoutdecoration.cpp [new file with mode: 0644]
src/designer/components/formeditor/default_layoutdecoration.h [new file with mode: 0644]
src/designer/components/formeditor/defaultbrushes.xml [new file with mode: 0644]
src/designer/components/formeditor/deviceprofiledialog.cpp [new file with mode: 0644]
src/designer/components/formeditor/deviceprofiledialog.h [new file with mode: 0644]
src/designer/components/formeditor/deviceprofiledialog.ui [new file with mode: 0644]
src/designer/components/formeditor/dpi_chooser.cpp [new file with mode: 0644]
src/designer/components/formeditor/dpi_chooser.h [new file with mode: 0644]
src/designer/components/formeditor/embeddedoptionspage.cpp [new file with mode: 0644]
src/designer/components/formeditor/embeddedoptionspage.h [new file with mode: 0644]
src/designer/components/formeditor/formeditor.cmake [new file with mode: 0644]
src/designer/components/formeditor/formeditor.cpp [new file with mode: 0644]
src/designer/components/formeditor/formeditor.h [new file with mode: 0644]
src/designer/components/formeditor/formeditor.qrc [new file with mode: 0644]
src/designer/components/formeditor/formeditor_global.h [new file with mode: 0644]
src/designer/components/formeditor/formeditor_optionspage.cpp [new file with mode: 0644]
src/designer/components/formeditor/formeditor_optionspage.h [new file with mode: 0644]
src/designer/components/formeditor/formwindow.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindow.h [new file with mode: 0644]
src/designer/components/formeditor/formwindow_dnditem.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindow_dnditem.h [new file with mode: 0644]
src/designer/components/formeditor/formwindow_widgetstack.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindow_widgetstack.h [new file with mode: 0644]
src/designer/components/formeditor/formwindowcursor.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindowcursor.h [new file with mode: 0644]
src/designer/components/formeditor/formwindowmanager.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindowmanager.h [new file with mode: 0644]
src/designer/components/formeditor/formwindowsettings.cpp [new file with mode: 0644]
src/designer/components/formeditor/formwindowsettings.h [new file with mode: 0644]
src/designer/components/formeditor/formwindowsettings.ui [new file with mode: 0644]
src/designer/components/formeditor/iconcache.cpp [new file with mode: 0644]
src/designer/components/formeditor/iconcache.h [new file with mode: 0644]
src/designer/components/formeditor/images/cleartext.png [new file with mode: 0644]
src/designer/components/formeditor/images/color.png [new file with mode: 0644]
src/designer/components/formeditor/images/configure.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/arrow.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/busy.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/closedhand.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/cross.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/hand.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/hsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/ibeam.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/no.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/openhand.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/sizeall.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/sizeb.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/sizef.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/sizeh.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/sizev.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/uparrow.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/vsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/wait.png [new file with mode: 0644]
src/designer/components/formeditor/images/cursors/whatsthis.png [new file with mode: 0644]
src/designer/components/formeditor/images/downplus.png [new file with mode: 0644]
src/designer/components/formeditor/images/dropdownbutton.png [new file with mode: 0644]
src/designer/components/formeditor/images/edit.png [new file with mode: 0644]
src/designer/components/formeditor/images/editdelete-16.png [new file with mode: 0644]
src/designer/components/formeditor/images/emptyicon.png [new file with mode: 0644]
src/designer/components/formeditor/images/filenew-16.png [new file with mode: 0644]
src/designer/components/formeditor/images/fileopen-16.png [new file with mode: 0644]
src/designer/components/formeditor/images/leveldown.png [new file with mode: 0644]
src/designer/components/formeditor/images/levelup.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/adjustsize.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/back.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/buddytool.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/down.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editbreaklayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editcopy.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editcut.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editdelete.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editform.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editgrid.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/edithlayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/edithlayoutsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editlower.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editpaste.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editraise.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editvlayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/editvlayoutsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/filenew.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/fileopen.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/filesave.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/forward.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/insertimage.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/minus.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/plus.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/redo.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/resetproperty.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/resourceeditortool.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/signalslottool.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/simplifyrichtext.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/tabordertool.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textanchor.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textbold.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textcenter.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textitalic.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textjustify.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textleft.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textright.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textsubscript.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textsuperscript.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/textunder.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/undo.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/up.png [new file with mode: 0644]
src/designer/components/formeditor/images/mac/widgettool.png [new file with mode: 0644]
src/designer/components/formeditor/images/minus-16.png [new file with mode: 0644]
src/designer/components/formeditor/images/plus-16.png [new file with mode: 0644]
src/designer/components/formeditor/images/prefix-add.png [new file with mode: 0644]
src/designer/components/formeditor/images/qt3logo.png [new file with mode: 0644]
src/designer/components/formeditor/images/qtlogo.png [new file with mode: 0644]
src/designer/components/formeditor/images/reload.png [new file with mode: 0644]
src/designer/components/formeditor/images/resetproperty.png [new file with mode: 0644]
src/designer/components/formeditor/images/sort.png [new file with mode: 0644]
src/designer/components/formeditor/images/submenu.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/calendarwidget.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/checkbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/columnview.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/combobox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/commandlinkbutton.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/dateedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/datetimeedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/dial.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/dialogbuttonbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/dockwidget.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/doublespinbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/fontcombobox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/frame.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/graphicsview.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/groupbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/groupboxcollapsible.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/hscrollbar.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/hslider.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/hsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/label.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/lcdnumber.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/line.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/lineedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/listbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/listview.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/mdiarea.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/plaintextedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/progress.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/pushbutton.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/radiobutton.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/scrollarea.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/spacer.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/spinbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/tabbar.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/table.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/tabwidget.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/textedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/timeedit.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/toolbox.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/toolbutton.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/vline.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/vscrollbar.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/vslider.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/vspacer.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/widget.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/widgetstack.png [new file with mode: 0644]
src/designer/components/formeditor/images/widgets/wizard.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/adjustsize.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/back.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/buddytool.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/down.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editbreaklayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editcopy.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editcut.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editdelete.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editform.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editgrid.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/edithlayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/edithlayoutsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editlower.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editpaste.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editraise.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editvlayout.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/editvlayoutsplit.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/filenew.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/fileopen.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/filesave.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/forward.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/insertimage.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/minus.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/plus.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/redo.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/resourceeditortool.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/signalslottool.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/simplifyrichtext.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/tabordertool.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textanchor.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textbold.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textcenter.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textitalic.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textjustify.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textleft.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textright.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textsubscript.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textsuperscript.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/textunder.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/undo.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/up.png [new file with mode: 0644]
src/designer/components/formeditor/images/win/widgettool.png [new file with mode: 0644]
src/designer/components/formeditor/itemview_propertysheet.cpp [new file with mode: 0644]
src/designer/components/formeditor/itemview_propertysheet.h [new file with mode: 0644]
src/designer/components/formeditor/layout_propertysheet.cpp [new file with mode: 0644]
src/designer/components/formeditor/layout_propertysheet.h [new file with mode: 0644]
src/designer/components/formeditor/line_propertysheet.cpp [new file with mode: 0644]
src/designer/components/formeditor/line_propertysheet.h [new file with mode: 0644]
src/designer/components/formeditor/previewactiongroup.cpp [new file with mode: 0644]
src/designer/components/formeditor/previewactiongroup.h [new file with mode: 0644]
src/designer/components/formeditor/qdesigner_resource.cpp [new file with mode: 0644]
src/designer/components/formeditor/qdesigner_resource.h [new file with mode: 0644]
src/designer/components/formeditor/qdesignerundostack.cpp [new file with mode: 0644]
src/designer/components/formeditor/qdesignerundostack.h [new file with mode: 0644]
src/designer/components/formeditor/qlayoutwidget_propertysheet.cpp [new file with mode: 0644]
src/designer/components/formeditor/qlayoutwidget_propertysheet.h [new file with mode: 0644]
src/designer/components/formeditor/qmainwindow_container.cpp [new file with mode: 0644]
src/designer/components/formeditor/qmainwindow_container.h [new file with mode: 0644]
src/designer/components/formeditor/qmdiarea_container.cpp [new file with mode: 0644]
src/designer/components/formeditor/qmdiarea_container.h [new file with mode: 0644]
src/designer/components/formeditor/qtbrushmanager.cpp [new file with mode: 0644]
src/designer/components/formeditor/qtbrushmanager.h [new file with mode: 0644]
src/designer/components/formeditor/qwizard_container.cpp [new file with mode: 0644]
src/designer/components/formeditor/qwizard_container.h [new file with mode: 0644]
src/designer/components/formeditor/qworkspace_container.cpp [new file with mode: 0644]
src/designer/components/formeditor/qworkspace_container.h [new file with mode: 0644]
src/designer/components/formeditor/spacer_propertysheet.cpp [new file with mode: 0644]
src/designer/components/formeditor/spacer_propertysheet.h [new file with mode: 0644]
src/designer/components/formeditor/templateoptionspage.cpp [new file with mode: 0644]
src/designer/components/formeditor/templateoptionspage.h [new file with mode: 0644]
src/designer/components/formeditor/templateoptionspage.ui [new file with mode: 0644]
src/designer/components/formeditor/tool_widgeteditor.cpp [new file with mode: 0644]
src/designer/components/formeditor/tool_widgeteditor.h [new file with mode: 0644]
src/designer/components/formeditor/widgetselection.cpp [new file with mode: 0644]
src/designer/components/formeditor/widgetselection.h [new file with mode: 0644]
src/designer/components/objectinspector/objectinspector.cmake [new file with mode: 0644]
src/designer/components/objectinspector/objectinspector.cpp [new file with mode: 0644]
src/designer/components/objectinspector/objectinspector.h [new file with mode: 0644]
src/designer/components/objectinspector/objectinspector_global.h [new file with mode: 0644]
src/designer/components/objectinspector/objectinspectormodel.cpp [new file with mode: 0644]
src/designer/components/objectinspector/objectinspectormodel_p.h [new file with mode: 0644]
src/designer/components/propertyeditor/brushpropertymanager.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/brushpropertymanager.h [new file with mode: 0644]
src/designer/components/propertyeditor/designerpropertymanager.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/designerpropertymanager.h [new file with mode: 0644]
src/designer/components/propertyeditor/fontmapping.xml [new file with mode: 0644]
src/designer/components/propertyeditor/fontpropertymanager.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/fontpropertymanager.h [new file with mode: 0644]
src/designer/components/propertyeditor/newdynamicpropertydialog.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/newdynamicpropertydialog.h [new file with mode: 0644]
src/designer/components/propertyeditor/newdynamicpropertydialog.ui [new file with mode: 0644]
src/designer/components/propertyeditor/paletteeditor.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/paletteeditor.h [new file with mode: 0644]
src/designer/components/propertyeditor/paletteeditor.ui [new file with mode: 0644]
src/designer/components/propertyeditor/paletteeditorbutton.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/paletteeditorbutton.h [new file with mode: 0644]
src/designer/components/propertyeditor/previewframe.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/previewframe.h [new file with mode: 0644]
src/designer/components/propertyeditor/previewwidget.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/previewwidget.h [new file with mode: 0644]
src/designer/components/propertyeditor/previewwidget.ui [new file with mode: 0644]
src/designer/components/propertyeditor/propertyeditor.cmake [new file with mode: 0644]
src/designer/components/propertyeditor/propertyeditor.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/propertyeditor.h [new file with mode: 0644]
src/designer/components/propertyeditor/propertyeditor.qrc [new file with mode: 0644]
src/designer/components/propertyeditor/propertyeditor_global.h [new file with mode: 0644]
src/designer/components/propertyeditor/qlonglongvalidator.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/qlonglongvalidator.h [new file with mode: 0644]
src/designer/components/propertyeditor/stringlisteditor.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/stringlisteditor.h [new file with mode: 0644]
src/designer/components/propertyeditor/stringlisteditor.ui [new file with mode: 0644]
src/designer/components/propertyeditor/stringlisteditorbutton.cpp [new file with mode: 0644]
src/designer/components/propertyeditor/stringlisteditorbutton.h [new file with mode: 0644]
src/designer/components/qdesigner_components.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/connectdialog.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/connectdialog.ui [new file with mode: 0644]
src/designer/components/signalsloteditor/connectdialog_p.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalslot_utils.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalslot_utils_p.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor.cmake [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_global.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_instance.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_p.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_plugin.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_plugin.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_tool.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditor_tool.h [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditorwindow.cpp [new file with mode: 0644]
src/designer/components/signalsloteditor/signalsloteditorwindow.h [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor.cmake [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor.cpp [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor.h [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_global.h [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_instance.cpp [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_plugin.cpp [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_plugin.h [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_tool.cpp [new file with mode: 0644]
src/designer/components/tabordereditor/tabordereditor_tool.h [new file with mode: 0644]
src/designer/components/taskmenu/button_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/button_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/combobox_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/combobox_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/containerwidget_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/containerwidget_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/groupbox_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/groupbox_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/inplace_editor.cpp [new file with mode: 0644]
src/designer/components/taskmenu/inplace_editor.h [new file with mode: 0644]
src/designer/components/taskmenu/inplace_widget_helper.cpp [new file with mode: 0644]
src/designer/components/taskmenu/inplace_widget_helper.h [new file with mode: 0644]
src/designer/components/taskmenu/itemlisteditor.cpp [new file with mode: 0644]
src/designer/components/taskmenu/itemlisteditor.h [new file with mode: 0644]
src/designer/components/taskmenu/itemlisteditor.ui [new file with mode: 0644]
src/designer/components/taskmenu/label_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/label_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/layouttaskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/layouttaskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/lineedit_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/lineedit_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/listwidget_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/listwidget_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/listwidgeteditor.cpp [new file with mode: 0644]
src/designer/components/taskmenu/listwidgeteditor.h [new file with mode: 0644]
src/designer/components/taskmenu/menutaskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/menutaskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/tablewidget_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/tablewidget_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/tablewidgeteditor.cpp [new file with mode: 0644]
src/designer/components/taskmenu/tablewidgeteditor.h [new file with mode: 0644]
src/designer/components/taskmenu/tablewidgeteditor.ui [new file with mode: 0644]
src/designer/components/taskmenu/taskmenu.cmake [new file with mode: 0644]
src/designer/components/taskmenu/taskmenu_component.cpp [new file with mode: 0644]
src/designer/components/taskmenu/taskmenu_component.h [new file with mode: 0644]
src/designer/components/taskmenu/taskmenu_global.h [new file with mode: 0644]
src/designer/components/taskmenu/textedit_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/textedit_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/toolbar_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/toolbar_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/treewidget_taskmenu.cpp [new file with mode: 0644]
src/designer/components/taskmenu/treewidget_taskmenu.h [new file with mode: 0644]
src/designer/components/taskmenu/treewidgeteditor.cpp [new file with mode: 0644]
src/designer/components/taskmenu/treewidgeteditor.h [new file with mode: 0644]
src/designer/components/taskmenu/treewidgeteditor.ui [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox.cmake [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox.cpp [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox.h [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox.qrc [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox.xml [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox_dnditem.cpp [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox_dnditem.h [new file with mode: 0644]
src/designer/components/widgetbox/widgetbox_global.h [new file with mode: 0644]
src/designer/components/widgetbox/widgetboxcategorylistview.cpp [new file with mode: 0644]
src/designer/components/widgetbox/widgetboxcategorylistview.h [new file with mode: 0644]
src/designer/components/widgetbox/widgetboxtreewidget.cpp [new file with mode: 0644]
src/designer/components/widgetbox/widgetboxtreewidget.h [new file with mode: 0644]
src/designer/data/generate_header.xsl [new file with mode: 0644]
src/designer/data/generate_impl.xsl [new file with mode: 0644]
src/designer/data/generate_shared.xsl [new file with mode: 0644]
src/designer/data/ui3.xsd [new file with mode: 0644]
src/designer/data/ui4.xsd [new file with mode: 0644]
src/designer/designer/CMakeLists.txt [new file with mode: 0644]
src/designer/designer/Info_mac.plist [new file with mode: 0644]
src/designer/designer/appfontdialog.cpp [new file with mode: 0644]
src/designer/designer/appfontdialog.h [new file with mode: 0644]
src/designer/designer/assistantclient.cpp [new file with mode: 0644]
src/designer/designer/assistantclient.h [new file with mode: 0644]
src/designer/designer/designer.icns [new file with mode: 0644]
src/designer/designer/designer.ico [new file with mode: 0644]
src/designer/designer/designer.pro [new file with mode: 0644]
src/designer/designer/designer.qrc [new file with mode: 0644]
src/designer/designer/designer.rc [new file with mode: 0644]
src/designer/designer/designer_enums.h [new file with mode: 0644]
src/designer/designer/fontpanel/fontpanel.cmake [new file with mode: 0644]
src/designer/designer/fontpanel/fontpanel.cpp [new file with mode: 0644]
src/designer/designer/fontpanel/fontpanel.h [new file with mode: 0644]
src/designer/designer/images/designer.png [new file with mode: 0644]
src/designer/designer/images/mdi.png [new file with mode: 0644]
src/designer/designer/images/sdi.png [new file with mode: 0644]
src/designer/designer/images/workbench.png [new file with mode: 0644]
src/designer/designer/main.cpp [new file with mode: 0644]
src/designer/designer/mainwindow.cpp [new file with mode: 0644]
src/designer/designer/mainwindow.h [new file with mode: 0644]
src/designer/designer/newform.cpp [new file with mode: 0644]
src/designer/designer/newform.h [new file with mode: 0644]
src/designer/designer/preferencesdialog.cpp [new file with mode: 0644]
src/designer/designer/preferencesdialog.h [new file with mode: 0644]
src/designer/designer/preferencesdialog.ui [new file with mode: 0644]
src/designer/designer/qdesigner.cpp [new file with mode: 0644]
src/designer/designer/qdesigner.h [new file with mode: 0644]
src/designer/designer/qdesigner_actions.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_actions.h [new file with mode: 0644]
src/designer/designer/qdesigner_appearanceoptions.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_appearanceoptions.h [new file with mode: 0644]
src/designer/designer/qdesigner_appearanceoptions.ui [new file with mode: 0644]
src/designer/designer/qdesigner_formwindow.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_formwindow.h [new file with mode: 0644]
src/designer/designer/qdesigner_pch.h [new file with mode: 0644]
src/designer/designer/qdesigner_server.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_server.h [new file with mode: 0644]
src/designer/designer/qdesigner_settings.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_settings.h [new file with mode: 0644]
src/designer/designer/qdesigner_toolwindow.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_toolwindow.h [new file with mode: 0644]
src/designer/designer/qdesigner_workbench.cpp [new file with mode: 0644]
src/designer/designer/qdesigner_workbench.h [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/back.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/down.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/forward.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/minus.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/plus.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/images/up.png [new file with mode: 0644]
src/designer/designer/qttoolbardialog/qttoolbardialog.cmake [new file with mode: 0644]
src/designer/designer/qttoolbardialog/qttoolbardialog.cpp [new file with mode: 0644]
src/designer/designer/qttoolbardialog/qttoolbardialog.h [new file with mode: 0644]
src/designer/designer/qttoolbardialog/qttoolbardialog.qrc [new file with mode: 0644]
src/designer/designer/qttoolbardialog/qttoolbardialog.ui [new file with mode: 0644]
src/designer/designer/saveformastemplate.cpp [new file with mode: 0644]
src/designer/designer/saveformastemplate.h [new file with mode: 0644]
src/designer/designer/saveformastemplate.ui [new file with mode: 0644]
src/designer/designer/uifile.icns [new file with mode: 0644]
src/designer/designer/versiondialog.cpp [new file with mode: 0644]
src/designer/designer/versiondialog.h [new file with mode: 0644]

diff --git a/README b/README
index 8cc9a7d..dbce917 100644 (file)
--- a/README
+++ b/README
@@ -5,8 +5,8 @@ on the latest Git revision of Qt v4.8.
 There are several things you should be aware before considering Katie:
 
  - some components and tools have been removed:
-  - QMake, Designer, D-Bus viewer, Linguist, Assistant, checksdk, macdeployqt,
-    pixeltool, qconfig, qdoc, qev, qvfb, runonphone and other non-essential
+  - QMake, D-Bus viewer, Linguist, Assistant, checksdk, macdeployqt, pixeltool,
+    qconfig, qdoc, qev, qvfb, runonphone and other non-essential
   - Qt3Support, QtWebKit and ActiveQt
 
  - some things have changed:
index 2acef47..dc20b7e 100644 (file)
@@ -8,7 +8,7 @@ set(KATIE_VERSION "${KATIE_MAJOR}.${KATIE_MINOR}.${KATIE_MICRO}")
 set(KATIE_STRING "katie ${KATIE_MAJOR}.${KATIE_MINOR}.${KATIE_MICRO}")
 set(KATIE_BUGREPORT "xakepa10@gmail.com")
 set(KATIE_URL "http://github.com/fluxer/katie")
-set(KATIE_COMPONENTS "Core Gui DBus Declarative Designer Help Multimedia Network OpenGL Phonon Sql Svg Xml XmlPatterns Script ScriptTools Test UiTools")
+set(KATIE_COMPONENTS "Core Gui DBus Declarative Designer DesignerComponents Help Multimedia Network OpenGL Phonon Sql Svg Xml XmlPatterns Script ScriptTools Test UiTools")
 # TODO: make dbus tools optional
 set(KATIE_TOOLS "moc uic rcc qdbusxml2cpp qdbuscpp2xml qhelpgenerator qcollectiongenerator lupdate lrelease lconvert")
 set(QT_LICENSE "Open Source")
index 6e9f7f6..a65101c 100644 (file)
@@ -8,6 +8,9 @@ include(extension/extension.cmake)
 include(sdk/sdk.cmake)
 include(shared/shared.cmake)
 
+add_subdirectory(components)
+add_subdirectory(designer)
+
 set(DESIGNER_PUBLIC_HEADERS
     ${DESIGNER_PUBLIC_HEADERS}
     QAbstractExtensionFactory
diff --git a/src/designer/components/CMakeLists.txt b/src/designer/components/CMakeLists.txt
new file mode 100644 (file)
index 0000000..cf73fcd
--- /dev/null
@@ -0,0 +1,120 @@
+add_definitions(-DQT_STATICPLUGIN)
+set(EXTRA_DESIGNERCOMPONENTS_LIBS KtCore KtGui KtXml KtDesigner KtScript)
+
+include(buddyeditor/buddyeditor.cmake)
+include(formeditor/formeditor.cmake)
+include(objectinspector/objectinspector.cmake)
+include(propertyeditor/propertyeditor.cmake)
+include(signalsloteditor/signalsloteditor.cmake)
+include(tabordereditor/tabordereditor.cmake)
+include(taskmenu/taskmenu.cmake)
+include(widgetbox/widgetbox.cmake)
+
+set(DESIGNERCOMPONENTS_PUBLIC_HEADERS
+    ${DESIGNERCOMPONENTS_PUBLIC_HEADERS}
+)
+
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_components.cpp
+)
+
+include_directories(
+    ${CMAKE_BINARY_DIR}/include
+    ${CMAKE_BINARY_DIR}/privateinclude
+    ${CMAKE_BINARY_DIR}/include/QtCore
+    ${CMAKE_BINARY_DIR}/privateinclude/QtCore
+    ${CMAKE_BINARY_DIR}/include/QtGui
+    ${CMAKE_BINARY_DIR}/privateinclude/QtGui
+    ${CMAKE_BINARY_DIR}/include/QtXml
+    ${CMAKE_BINARY_DIR}/privateinclude/QtXml
+    ${CMAKE_BINARY_DIR}/include/QtScript
+    ${CMAKE_BINARY_DIR}/privateinclude/QtScript
+    ${CMAKE_BINARY_DIR}/include/QtUiTools
+    ${CMAKE_BINARY_DIR}/privateinclude/QtUiTools
+    ${CMAKE_BINARY_DIR}/include/QtDesigner
+    ${CMAKE_BINARY_DIR}/privateinclude/QtDesigner
+    ${CMAKE_BINARY_DIR}/include/QtDesignerComponents
+    ${CMAKE_BINARY_DIR}/privateinclude/QtDesignerComponents
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox
+    ${CMAKE_CURRENT_BINARY_DIR}/buddyeditor
+    ${CMAKE_CURRENT_BINARY_DIR}/formeditor
+    ${CMAKE_CURRENT_BINARY_DIR}/objectinspector
+    ${CMAKE_CURRENT_BINARY_DIR}/propertyeditor
+    ${CMAKE_CURRENT_BINARY_DIR}/signalsloteditor
+    ${CMAKE_CURRENT_BINARY_DIR}/tabordereditor
+    ${CMAKE_CURRENT_BINARY_DIR}/taskmenu
+    ${CMAKE_CURRENT_BINARY_DIR}/widgetbox
+    ${CMAKE_SOURCE_DIR}/src/designer/components
+    ${CMAKE_SOURCE_DIR}/src/designer/sdk
+    ${CMAKE_SOURCE_DIR}/src/designer/extension
+    ${CMAKE_SOURCE_DIR}/src/designer/shared
+    ${CMAKE_SOURCE_DIR}/src/designer
+)
+
+if(KATIE_TYPE STREQUAL SHARED)
+    add_definitions(
+        -DQDESIGNER_SDK_LIBRARY
+        -DQDESIGNER_EXTENSION_LIBRARY
+        -DQDESIGNER_UILIB_LIBRARY
+        -DQDESIGNER_SHARED_LIBRARY
+        -DQDESIGNER_COMPONENTS_LIBRARY
+    )
+else()
+    add_definitions(-DQT_DESIGNER_STATIC)
+endif()
+
+# headers go in one place!
+katie_generate_misc("${DESIGNERCOMPONENTS_HEADERS}" QtDesignerComponents)
+katie_generate_public("${DESIGNERCOMPONENTS_PUBLIC_HEADERS}" QtDesignerComponents)
+katie_generate_map(
+    QtDesignerComponents
+    "QT_FORMEDITOR_EXPORT|QT_PROPERTYEDITOR_EXPORT|QT_SIGNALSLOTEDITOR_EXPORT|QT_OBJECTINSPECTOR_EXPORT|QT_WIDGETBOX_EXPORT|QT_BUDDYEDITOR_EXPORT|QT_TABORDEREDITOR_EXPORT|QT_TASKMENU_EXPORT"
+)
+katie_resources(${DESIGNERCOMPONENTS_SOURCES})
+katie_resources(${DESIGNERCOMPONENTS_HEADERS})
+katie_setup_flags()
+
+add_library(KtDesignerComponents ${KATIE_TYPE}
+    $<TARGET_OBJECTS:sharedfindwidget>
+    $<TARGET_OBJECTS:sharedqtpropertybrowser>
+    $<TARGET_OBJECTS:sharedqtgradienteditor>
+    ${DESIGNERCOMPONENTS_SOURCES} ${DESIGNERCOMPONENTS_HEADERS}
+)
+target_link_libraries(KtDesignerComponents ${EXTRA_DESIGNERCOMPONENTS_LIBS})
+set_target_properties(KtDesignerComponents PROPERTIES
+    VERSION ${KATIE_MAJOR}.${KATIE_MINOR}
+    SOVERSION ${KATIE_VERSION}
+    EXPORT_NAME DesignerComponents
+)
+
+katie_generate_package(
+    KtDesignerComponents
+    ""
+    "${EXTRA_DESIGNERCOMPONENTS_LIBS}"
+    "KtCore KtGui KtXml KtDesigner KtScript"
+)
+
+install(
+    TARGETS KtDesignerComponents
+    EXPORT KatieLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}
+    DESTINATION ${QT_LIBRARIES_PATH_INST}
+)
+
+install(
+    DIRECTORY ${CMAKE_BINARY_DIR}/include/QtDesignerComponents
+    DESTINATION ${QT_HEADERS_PATH_INST}
+    COMPONENT Devel
+)
diff --git a/src/designer/components/buddyeditor/buddyeditor.cmake b/src/designer/components/buddyeditor/buddyeditor.cmake
new file mode 100644 (file)
index 0000000..c83c964
--- /dev/null
@@ -0,0 +1,16 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_plugin.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_tool.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_global.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_tool.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_plugin.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/buddyeditor/buddyeditor_instance.cpp
+)
+
diff --git a/src/designer/components/buddyeditor/buddyeditor.cpp b/src/designer/components/buddyeditor/buddyeditor.cpp
new file mode 100644 (file)
index 0000000..dee4473
--- /dev/null
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "buddyeditor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/abstractformeditor.h>
+#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
+#include <moc_buddyeditor.h>
diff --git a/src/designer/components/buddyeditor/buddyeditor.h b/src/designer/components/buddyeditor/buddyeditor.h
new file mode 100644 (file)
index 0000000..88d10f3
--- /dev/null
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/buddyeditor/buddyeditor_global.h b/src/designer/components/buddyeditor/buddyeditor_global.h
new file mode 100644 (file)
index 0000000..0425768
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/buddyeditor/buddyeditor_instance.cpp b/src/designer/components/buddyeditor/buddyeditor_instance.cpp
new file mode 100644 (file)
index 0000000..f946bf1
--- /dev/null
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/buddyeditor/buddyeditor_plugin.cpp b/src/designer/components/buddyeditor/buddyeditor_plugin.cpp
new file mode 100644 (file)
index 0000000..96404c4
--- /dev/null
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QAction>
+
+#include "buddyeditor_plugin.h"
+#include "buddyeditor_tool.h"
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/abstractformeditor.h>
+
+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
+#include <moc_buddyeditor_plugin.h>
diff --git a/src/designer/components/buddyeditor/buddyeditor_plugin.h b/src/designer/components/buddyeditor/buddyeditor_plugin.h
new file mode 100644 (file)
index 0000000..e126e56
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_PLUGIN_H
+#define BUDDYEDITOR_PLUGIN_H
+
+#include "buddyeditor_global.h"
+
+#include <QtDesigner/abstractformeditorplugin.h>
+
+#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/components/buddyeditor/buddyeditor_tool.cpp b/src/designer/components/buddyeditor/buddyeditor_tool.cpp
new file mode 100644 (file)
index 0000000..060eb90
--- /dev/null
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "buddyeditor_tool.h"
+#include "buddyeditor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_buddyeditor_tool.h>
diff --git a/src/designer/components/buddyeditor/buddyeditor_tool.h b/src/designer/components/buddyeditor/buddyeditor_tool.h
new file mode 100644 (file)
index 0000000..c175812
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_TOOL_H
+#define BUDDYEDITOR_TOOL_H
+
+#include "buddyeditor_global.h"
+
+#include <QtCore/QPointer>
+
+#include <QtDesigner/abstractformwindowtool.h>
+
+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/components/formeditor/brushmanagerproxy.cpp b/src/designer/components/formeditor/brushmanagerproxy.cpp
new file mode 100644 (file)
index 0000000..868acca
--- /dev/null
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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"
+#include <moc_brushmanagerproxy.h>
diff --git a/src/designer/components/formeditor/brushmanagerproxy.h b/src/designer/components/formeditor/brushmanagerproxy.h
new file mode 100644 (file)
index 0000000..fa5bd95
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/default_actionprovider.cpp b/src/designer/components/formeditor/default_actionprovider.cpp
new file mode 100644 (file)
index 0000000..84560e0
--- /dev/null
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_default_actionprovider.h>
diff --git a/src/designer/components/formeditor/default_actionprovider.h b/src/designer/components/formeditor/default_actionprovider.h
new file mode 100644 (file)
index 0000000..9f0ff11
--- /dev/null
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/default_container.cpp b/src/designer/components/formeditor/default_container.cpp
new file mode 100644 (file)
index 0000000..3cbea5e
--- /dev/null
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_default_container.h>
diff --git a/src/designer/components/formeditor/default_container.h b/src/designer/components/formeditor/default_container.h
new file mode 100644 (file)
index 0000000..01c9aee
--- /dev/null
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_CONTAINER_H
+#define DEFAULT_CONTAINER_H
+
+#include <QtDesigner/container.h>
+#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/components/formeditor/default_layoutdecoration.cpp b/src/designer/components/formeditor/default_layoutdecoration.cpp
new file mode 100644 (file)
index 0000000..f0b13f4
--- /dev/null
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "default_layoutdecoration.h"
+#include "qlayout_widget_p.h"
+
+#include <layoutinfo_p.h>
+
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+
+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
+#include <moc_default_layoutdecoration.h>
diff --git a/src/designer/components/formeditor/default_layoutdecoration.h b/src/designer/components/formeditor/default_layoutdecoration.h
new file mode 100644 (file)
index 0000000..086264a
--- /dev/null
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_LAYOUTDECORATION_H
+#define DEFAULT_LAYOUTDECORATION_H
+
+#include "formeditor_global.h"
+#include <QtDesigner/layoutdecoration.h>
+#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/components/formeditor/defaultbrushes.xml b/src/designer/components/formeditor/defaultbrushes.xml
new file mode 100644 (file)
index 0000000..88035c3
--- /dev/null
@@ -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/components/formeditor/deviceprofiledialog.cpp b/src/designer/components/formeditor/deviceprofiledialog.cpp
new file mode 100644 (file)
index 0000000..e503c08
--- /dev/null
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_deviceprofiledialog.h>
diff --git a/src/designer/components/formeditor/deviceprofiledialog.h b/src/designer/components/formeditor/deviceprofiledialog.h
new file mode 100644 (file)
index 0000000..62f7822
--- /dev/null
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for 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/components/formeditor/deviceprofiledialog.ui b/src/designer/components/formeditor/deviceprofiledialog.ui
new file mode 100644 (file)
index 0000000..d7a298c
--- /dev/null
@@ -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/components/formeditor/dpi_chooser.cpp b/src/designer/components/formeditor/dpi_chooser.cpp
new file mode 100644 (file)
index 0000000..c8620ed
--- /dev/null
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_dpi_chooser.h>
diff --git a/src/designer/components/formeditor/dpi_chooser.h b/src/designer/components/formeditor/dpi_chooser.h
new file mode 100644 (file)
index 0000000..c528a54
--- /dev/null
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for 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/components/formeditor/embeddedoptionspage.cpp b/src/designer/components/formeditor/embeddedoptionspage.cpp
new file mode 100644 (file)
index 0000000..98201c5
--- /dev/null
@@ -0,0 +1,454 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+#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
+#include <moc_embeddedoptionspage.h>
diff --git a/src/designer/components/formeditor/embeddedoptionspage.h b/src/designer/components/formeditor/embeddedoptionspage.h
new file mode 100644 (file)
index 0000000..09f6ba9
--- /dev/null
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EMBEDDEDOPTIONSPAGE_H
+#define EMBEDDEDOPTIONSPAGE_H
+
+#include <QtDesigner/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/components/formeditor/formeditor.cmake b/src/designer/components/formeditor/formeditor.cmake
new file mode 100644 (file)
index 0000000..822e794
--- /dev/null
@@ -0,0 +1,77 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qdesigner_resource.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qdesignerundostack.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow_widgetstack.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow_dnditem.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowcursor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/widgetselection.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowmanager.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor_global.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qlayoutwidget_propertysheet.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/layout_propertysheet.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/spacer_propertysheet.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/line_propertysheet.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_container.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_actionprovider.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qmainwindow_container.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qworkspace_container.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qmdiarea_container.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qwizard_container.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_layoutdecoration.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qtbrushmanager.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/brushmanagerproxy.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/iconcache.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/tool_widgeteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor_optionspage.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/embeddedoptionspage.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowsettings.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/deviceprofiledialog.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/dpi_chooser.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/previewactiongroup.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/itemview_propertysheet.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/templateoptionspage.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/deviceprofiledialog.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowsettings.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/templateoptionspage.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qdesigner_resource.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qdesignerundostack.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow_widgetstack.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindow_dnditem.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowcursor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/widgetselection.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowmanager.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qlayoutwidget_propertysheet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/layout_propertysheet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/spacer_propertysheet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/line_propertysheet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qmainwindow_container.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qworkspace_container.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qmdiarea_container.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qwizard_container.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_container.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_layoutdecoration.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/default_actionprovider.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/tool_widgeteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/qtbrushmanager.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/brushmanagerproxy.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/iconcache.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor_optionspage.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/embeddedoptionspage.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formwindowsettings.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/deviceprofiledialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/dpi_chooser.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/previewactiongroup.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/itemview_propertysheet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/templateoptionspage.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/formeditor/formeditor.qrc
+)
+
diff --git a/src/designer/components/formeditor/formeditor.cpp b/src/designer/components/formeditor/formeditor.cpp
new file mode 100644 (file)
index 0000000..9c9d530
--- /dev/null
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+
+#include <moc_formeditor.h>
+#include <qrc_formeditor.cpp>
diff --git a/src/designer/components/formeditor/formeditor.h b/src/designer/components/formeditor/formeditor.h
new file mode 100644 (file)
index 0000000..8015636
--- /dev/null
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMEDITOR_H
+#define FORMEDITOR_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/abstractformeditor.h>
+
+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/components/formeditor/formeditor.qrc b/src/designer/components/formeditor/formeditor.qrc
new file mode 100644 (file)
index 0000000..e42cc66
--- /dev/null
@@ -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/components/formeditor/formeditor_global.h b/src/designer/components/formeditor/formeditor_global.h
new file mode 100644 (file)
index 0000000..68a4d69
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/formeditor_optionspage.cpp b/src/designer/components/formeditor/formeditor_optionspage.cpp
new file mode 100644 (file)
index 0000000..0130538
--- /dev/null
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+#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/components/formeditor/formeditor_optionspage.h b/src/designer/components/formeditor/formeditor_optionspage.h
new file mode 100644 (file)
index 0000000..776b154
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMEDITOR_OPTIONSPAGE_H
+#define FORMEDITOR_OPTIONSPAGE_H
+
+#include <QtDesigner/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/components/formeditor/formwindow.cpp b/src/designer/components/formeditor/formwindow.cpp
new file mode 100644 (file)
index 0000000..f941e74
--- /dev/null
@@ -0,0 +1,2983 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractwidgetdatabase.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/abstractwidgetfactory.h>
+#include <QtDesigner/container.h>
+#include <QtDesigner/taskmenu.h>
+#include <QtDesigner/abstractwidgetbox.h>
+#include <abstractdialoggui_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/QBuffer>
+#include <QtCore/QTimer>
+#include <QtCore/qxmlstream.h>
+#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>
+#include <QtGui/qpen.h>
+
+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 != ocend; ++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
+
+#include <moc_formwindow.h>
diff --git a/src/designer/components/formeditor/formwindow.h b/src/designer/components/formeditor/formwindow.h
new file mode 100644 (file)
index 0000000..8f0e6ec
--- /dev/null
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/formwindow_dnditem.cpp b/src/designer/components/formeditor/formwindow_dnditem.cpp
new file mode 100644 (file)
index 0000000..0d93f05
--- /dev/null
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formwindow_dnditem.h"
+#include "formwindow.h"
+
+#include <ui4_p.h>
+#include <qdesigner_resource.h>
+#include <qtresourcemodel_p.h>
+
+#include <QtDesigner/abstractformeditor.h>
+
+#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/components/formeditor/formwindow_dnditem.h b/src/designer/components/formeditor/formwindow_dnditem.h
new file mode 100644 (file)
index 0000000..d7297e7
--- /dev/null
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/formwindow_widgetstack.cpp b/src/designer/components/formeditor/formwindow_widgetstack.cpp
new file mode 100644 (file)
index 0000000..3c51e5a
--- /dev/null
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formwindow_widgetstack.h"
+#include <QtDesigner/abstractformwindowtool.h>
+
+#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
+#include <moc_formwindow_widgetstack.h>
diff --git a/src/designer/components/formeditor/formwindow_widgetstack.h b/src/designer/components/formeditor/formwindow_widgetstack.h
new file mode 100644 (file)
index 0000000..b4ef592
--- /dev/null
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/formwindowcursor.cpp b/src/designer/components/formeditor/formwindowcursor.cpp
new file mode 100644 (file)
index 0000000..7601b9c
--- /dev/null
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_formwindowcursor.h>
diff --git a/src/designer/components/formeditor/formwindowcursor.h b/src/designer/components/formeditor/formwindowcursor.h
new file mode 100644 (file)
index 0000000..80fe171
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOWCURSOR_H
+#define FORMWINDOWCURSOR_H
+
+#include "formeditor_global.h"
+#include "formwindow.h"
+#include <QtDesigner/abstractformwindowcursor.h>
+
+#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/components/formeditor/formwindowmanager.cpp b/src/designer/components/formeditor/formwindowmanager.cpp
new file mode 100644 (file)
index 0000000..0d72003
--- /dev/null
@@ -0,0 +1,1037 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractlanguage.h>
+#include <QtDesigner/container.h>
+#include <QtDesigner/abstractwidgetbox.h>
+#include <QtDesigner/abstractintegration.h>
+
+#include <QtGui/QUndoGroup>
+#include <QtGui/QAction>
+#include <QtGui/QSplitter>
+#include <QtGui/qevent.h>
+#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
+#include <moc_formwindowmanager.h>
diff --git a/src/designer/components/formeditor/formwindowmanager.h b/src/designer/components/formeditor/formwindowmanager.h
new file mode 100644 (file)
index 0000000..a341168
--- /dev/null
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOWMANAGER_H
+#define FORMWINDOWMANAGER_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/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/components/formeditor/formwindowsettings.cpp b/src/designer/components/formeditor/formwindowsettings.cpp
new file mode 100644 (file)
index 0000000..8e18443
--- /dev/null
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_formwindowsettings.h>
diff --git a/src/designer/components/formeditor/formwindowsettings.h b/src/designer/components/formeditor/formwindowsettings.h
new file mode 100644 (file)
index 0000000..8bcf7b2
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/formwindowsettings.ui b/src/designer/components/formeditor/formwindowsettings.ui
new file mode 100644 (file)
index 0000000..01caac0
--- /dev/null
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/iconcache.cpp b/src/designer/components/formeditor/iconcache.cpp
new file mode 100644 (file)
index 0000000..e11b415
--- /dev/null
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_iconcache.h>
diff --git a/src/designer/components/formeditor/iconcache.h b/src/designer/components/formeditor/iconcache.h
new file mode 100644 (file)
index 0000000..3e083b4
--- /dev/null
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ICONCACHE_H
+#define ICONCACHE_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/abstracticoncache.h>
+
+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/components/formeditor/images/cleartext.png b/src/designer/components/formeditor/images/cleartext.png
new file mode 100644 (file)
index 0000000..74133ba
Binary files /dev/null and b/src/designer/components/formeditor/images/cleartext.png differ
diff --git a/src/designer/components/formeditor/images/color.png b/src/designer/components/formeditor/images/color.png
new file mode 100644 (file)
index 0000000..54b7ebc
Binary files /dev/null and b/src/designer/components/formeditor/images/color.png differ
diff --git a/src/designer/components/formeditor/images/configure.png b/src/designer/components/formeditor/images/configure.png
new file mode 100644 (file)
index 0000000..d9f2fd8
Binary files /dev/null and b/src/designer/components/formeditor/images/configure.png differ
diff --git a/src/designer/components/formeditor/images/cursors/arrow.png b/src/designer/components/formeditor/images/cursors/arrow.png
new file mode 100644 (file)
index 0000000..a69ef4e
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/arrow.png differ
diff --git a/src/designer/components/formeditor/images/cursors/busy.png b/src/designer/components/formeditor/images/cursors/busy.png
new file mode 100644 (file)
index 0000000..53717e4
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/busy.png differ
diff --git a/src/designer/components/formeditor/images/cursors/closedhand.png b/src/designer/components/formeditor/images/cursors/closedhand.png
new file mode 100644 (file)
index 0000000..b78dd1d
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/closedhand.png differ
diff --git a/src/designer/components/formeditor/images/cursors/cross.png b/src/designer/components/formeditor/images/cursors/cross.png
new file mode 100644 (file)
index 0000000..fe38e74
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/cross.png differ
diff --git a/src/designer/components/formeditor/images/cursors/hand.png b/src/designer/components/formeditor/images/cursors/hand.png
new file mode 100644 (file)
index 0000000..d2004ae
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/hand.png differ
diff --git a/src/designer/components/formeditor/images/cursors/hsplit.png b/src/designer/components/formeditor/images/cursors/hsplit.png
new file mode 100644 (file)
index 0000000..a5667e3
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/hsplit.png differ
diff --git a/src/designer/components/formeditor/images/cursors/ibeam.png b/src/designer/components/formeditor/images/cursors/ibeam.png
new file mode 100644 (file)
index 0000000..097fc5f
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/ibeam.png differ
diff --git a/src/designer/components/formeditor/images/cursors/no.png b/src/designer/components/formeditor/images/cursors/no.png
new file mode 100644 (file)
index 0000000..2b08c4e
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/no.png differ
diff --git a/src/designer/components/formeditor/images/cursors/openhand.png b/src/designer/components/formeditor/images/cursors/openhand.png
new file mode 100644 (file)
index 0000000..9181c85
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/openhand.png differ
diff --git a/src/designer/components/formeditor/images/cursors/sizeall.png b/src/designer/components/formeditor/images/cursors/sizeall.png
new file mode 100644 (file)
index 0000000..69f13eb
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/sizeall.png differ
diff --git a/src/designer/components/formeditor/images/cursors/sizeb.png b/src/designer/components/formeditor/images/cursors/sizeb.png
new file mode 100644 (file)
index 0000000..3b127a0
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/sizeb.png differ
diff --git a/src/designer/components/formeditor/images/cursors/sizef.png b/src/designer/components/formeditor/images/cursors/sizef.png
new file mode 100644 (file)
index 0000000..f37d7b9
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/sizef.png differ
diff --git a/src/designer/components/formeditor/images/cursors/sizeh.png b/src/designer/components/formeditor/images/cursors/sizeh.png
new file mode 100644 (file)
index 0000000..a9f40cb
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/sizeh.png differ
diff --git a/src/designer/components/formeditor/images/cursors/sizev.png b/src/designer/components/formeditor/images/cursors/sizev.png
new file mode 100644 (file)
index 0000000..1edbab2
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/sizev.png differ
diff --git a/src/designer/components/formeditor/images/cursors/uparrow.png b/src/designer/components/formeditor/images/cursors/uparrow.png
new file mode 100644 (file)
index 0000000..d3e70ef
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/uparrow.png differ
diff --git a/src/designer/components/formeditor/images/cursors/vsplit.png b/src/designer/components/formeditor/images/cursors/vsplit.png
new file mode 100644 (file)
index 0000000..1beda25
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/vsplit.png differ
diff --git a/src/designer/components/formeditor/images/cursors/wait.png b/src/designer/components/formeditor/images/cursors/wait.png
new file mode 100644 (file)
index 0000000..69056c4
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/wait.png differ
diff --git a/src/designer/components/formeditor/images/cursors/whatsthis.png b/src/designer/components/formeditor/images/cursors/whatsthis.png
new file mode 100644 (file)
index 0000000..b47601c
Binary files /dev/null and b/src/designer/components/formeditor/images/cursors/whatsthis.png differ
diff --git a/src/designer/components/formeditor/images/downplus.png b/src/designer/components/formeditor/images/downplus.png
new file mode 100644 (file)
index 0000000..1e384a7
Binary files /dev/null and b/src/designer/components/formeditor/images/downplus.png differ
diff --git a/src/designer/components/formeditor/images/dropdownbutton.png b/src/designer/components/formeditor/images/dropdownbutton.png
new file mode 100644 (file)
index 0000000..5dd9649
Binary files /dev/null and b/src/designer/components/formeditor/images/dropdownbutton.png differ
diff --git a/src/designer/components/formeditor/images/edit.png b/src/designer/components/formeditor/images/edit.png
new file mode 100644 (file)
index 0000000..a5e49ad
Binary files /dev/null and b/src/designer/components/formeditor/images/edit.png differ
diff --git a/src/designer/components/formeditor/images/editdelete-16.png b/src/designer/components/formeditor/images/editdelete-16.png
new file mode 100644 (file)
index 0000000..ef5c799
Binary files /dev/null and b/src/designer/components/formeditor/images/editdelete-16.png differ
diff --git a/src/designer/components/formeditor/images/emptyicon.png b/src/designer/components/formeditor/images/emptyicon.png
new file mode 100644 (file)
index 0000000..897220e
Binary files /dev/null and b/src/designer/components/formeditor/images/emptyicon.png differ
diff --git a/src/designer/components/formeditor/images/filenew-16.png b/src/designer/components/formeditor/images/filenew-16.png
new file mode 100644 (file)
index 0000000..eefb3c5
Binary files /dev/null and b/src/designer/components/formeditor/images/filenew-16.png differ
diff --git a/src/designer/components/formeditor/images/fileopen-16.png b/src/designer/components/formeditor/images/fileopen-16.png
new file mode 100644 (file)
index 0000000..d832c62
Binary files /dev/null and b/src/designer/components/formeditor/images/fileopen-16.png differ
diff --git a/src/designer/components/formeditor/images/leveldown.png b/src/designer/components/formeditor/images/leveldown.png
new file mode 100644 (file)
index 0000000..742b7fb
Binary files /dev/null and b/src/designer/components/formeditor/images/leveldown.png differ
diff --git a/src/designer/components/formeditor/images/levelup.png b/src/designer/components/formeditor/images/levelup.png
new file mode 100644 (file)
index 0000000..48b3e89
Binary files /dev/null and b/src/designer/components/formeditor/images/levelup.png differ
diff --git a/src/designer/components/formeditor/images/mac/adjustsize.png b/src/designer/components/formeditor/images/mac/adjustsize.png
new file mode 100644 (file)
index 0000000..c4d884c
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/adjustsize.png differ
diff --git a/src/designer/components/formeditor/images/mac/back.png b/src/designer/components/formeditor/images/mac/back.png
new file mode 100644 (file)
index 0000000..e58177f
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/back.png differ
diff --git a/src/designer/components/formeditor/images/mac/buddytool.png b/src/designer/components/formeditor/images/mac/buddytool.png
new file mode 100644 (file)
index 0000000..2a42870
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/buddytool.png differ
diff --git a/src/designer/components/formeditor/images/mac/down.png b/src/designer/components/formeditor/images/mac/down.png
new file mode 100644 (file)
index 0000000..29d1d44
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/down.png differ
diff --git a/src/designer/components/formeditor/images/mac/editbreaklayout.png b/src/designer/components/formeditor/images/mac/editbreaklayout.png
new file mode 100644 (file)
index 0000000..dc00559
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editbreaklayout.png differ
diff --git a/src/designer/components/formeditor/images/mac/editcopy.png b/src/designer/components/formeditor/images/mac/editcopy.png
new file mode 100644 (file)
index 0000000..f551364
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editcopy.png differ
diff --git a/src/designer/components/formeditor/images/mac/editcut.png b/src/designer/components/formeditor/images/mac/editcut.png
new file mode 100644 (file)
index 0000000..a784fd5
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editcut.png differ
diff --git a/src/designer/components/formeditor/images/mac/editdelete.png b/src/designer/components/formeditor/images/mac/editdelete.png
new file mode 100644 (file)
index 0000000..201b31c
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editdelete.png differ
diff --git a/src/designer/components/formeditor/images/mac/editform.png b/src/designer/components/formeditor/images/mac/editform.png
new file mode 100644 (file)
index 0000000..4fc2e40
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editform.png differ
diff --git a/src/designer/components/formeditor/images/mac/editgrid.png b/src/designer/components/formeditor/images/mac/editgrid.png
new file mode 100644 (file)
index 0000000..bba4a69
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editgrid.png differ
diff --git a/src/designer/components/formeditor/images/mac/edithlayout.png b/src/designer/components/formeditor/images/mac/edithlayout.png
new file mode 100644 (file)
index 0000000..ec880bb
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/edithlayout.png differ
diff --git a/src/designer/components/formeditor/images/mac/edithlayoutsplit.png b/src/designer/components/formeditor/images/mac/edithlayoutsplit.png
new file mode 100644 (file)
index 0000000..227d011
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/edithlayoutsplit.png differ
diff --git a/src/designer/components/formeditor/images/mac/editlower.png b/src/designer/components/formeditor/images/mac/editlower.png
new file mode 100644 (file)
index 0000000..347806f
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editlower.png differ
diff --git a/src/designer/components/formeditor/images/mac/editpaste.png b/src/designer/components/formeditor/images/mac/editpaste.png
new file mode 100644 (file)
index 0000000..64c0b2d
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editpaste.png differ
diff --git a/src/designer/components/formeditor/images/mac/editraise.png b/src/designer/components/formeditor/images/mac/editraise.png
new file mode 100644 (file)
index 0000000..09cbbd7
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editraise.png differ
diff --git a/src/designer/components/formeditor/images/mac/editvlayout.png b/src/designer/components/formeditor/images/mac/editvlayout.png
new file mode 100644 (file)
index 0000000..63b26cd
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editvlayout.png differ
diff --git a/src/designer/components/formeditor/images/mac/editvlayoutsplit.png b/src/designer/components/formeditor/images/mac/editvlayoutsplit.png
new file mode 100644 (file)
index 0000000..5a02c94
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/editvlayoutsplit.png differ
diff --git a/src/designer/components/formeditor/images/mac/filenew.png b/src/designer/components/formeditor/images/mac/filenew.png
new file mode 100644 (file)
index 0000000..9dcba42
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/filenew.png differ
diff --git a/src/designer/components/formeditor/images/mac/fileopen.png b/src/designer/components/formeditor/images/mac/fileopen.png
new file mode 100644 (file)
index 0000000..c12bcd5
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/fileopen.png differ
diff --git a/src/designer/components/formeditor/images/mac/filesave.png b/src/designer/components/formeditor/images/mac/filesave.png
new file mode 100644 (file)
index 0000000..b41ecf5
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/filesave.png differ
diff --git a/src/designer/components/formeditor/images/mac/forward.png b/src/designer/components/formeditor/images/mac/forward.png
new file mode 100644 (file)
index 0000000..34b91f0
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/forward.png differ
diff --git a/src/designer/components/formeditor/images/mac/insertimage.png b/src/designer/components/formeditor/images/mac/insertimage.png
new file mode 100644 (file)
index 0000000..b8673e1
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/insertimage.png differ
diff --git a/src/designer/components/formeditor/images/mac/minus.png b/src/designer/components/formeditor/images/mac/minus.png
new file mode 100644 (file)
index 0000000..8d2eaed
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/minus.png differ
diff --git a/src/designer/components/formeditor/images/mac/plus.png b/src/designer/components/formeditor/images/mac/plus.png
new file mode 100644 (file)
index 0000000..1ee4542
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/plus.png differ
diff --git a/src/designer/components/formeditor/images/mac/redo.png b/src/designer/components/formeditor/images/mac/redo.png
new file mode 100644 (file)
index 0000000..8875bf2
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/redo.png differ
diff --git a/src/designer/components/formeditor/images/mac/resetproperty.png b/src/designer/components/formeditor/images/mac/resetproperty.png
new file mode 100644 (file)
index 0000000..9048252
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/resetproperty.png differ
diff --git a/src/designer/components/formeditor/images/mac/resourceeditortool.png b/src/designer/components/formeditor/images/mac/resourceeditortool.png
new file mode 100644 (file)
index 0000000..7ef511c
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/resourceeditortool.png differ
diff --git a/src/designer/components/formeditor/images/mac/signalslottool.png b/src/designer/components/formeditor/images/mac/signalslottool.png
new file mode 100644 (file)
index 0000000..71c9b07
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/signalslottool.png differ
diff --git a/src/designer/components/formeditor/images/mac/simplifyrichtext.png b/src/designer/components/formeditor/images/mac/simplifyrichtext.png
new file mode 100644 (file)
index 0000000..a48e974
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/simplifyrichtext.png differ
diff --git a/src/designer/components/formeditor/images/mac/tabordertool.png b/src/designer/components/formeditor/images/mac/tabordertool.png
new file mode 100644 (file)
index 0000000..f54faf9
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/tabordertool.png differ
diff --git a/src/designer/components/formeditor/images/mac/textanchor.png b/src/designer/components/formeditor/images/mac/textanchor.png
new file mode 100644 (file)
index 0000000..baa9dda
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textanchor.png differ
diff --git a/src/designer/components/formeditor/images/mac/textbold.png b/src/designer/components/formeditor/images/mac/textbold.png
new file mode 100644 (file)
index 0000000..38400bd
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textbold.png differ
diff --git a/src/designer/components/formeditor/images/mac/textcenter.png b/src/designer/components/formeditor/images/mac/textcenter.png
new file mode 100644 (file)
index 0000000..2ef5b2e
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textcenter.png differ
diff --git a/src/designer/components/formeditor/images/mac/textitalic.png b/src/designer/components/formeditor/images/mac/textitalic.png
new file mode 100644 (file)
index 0000000..0170ee2
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textitalic.png differ
diff --git a/src/designer/components/formeditor/images/mac/textjustify.png b/src/designer/components/formeditor/images/mac/textjustify.png
new file mode 100644 (file)
index 0000000..39cd6c1
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textjustify.png differ
diff --git a/src/designer/components/formeditor/images/mac/textleft.png b/src/designer/components/formeditor/images/mac/textleft.png
new file mode 100644 (file)
index 0000000..83a66d5
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textleft.png differ
diff --git a/src/designer/components/formeditor/images/mac/textright.png b/src/designer/components/formeditor/images/mac/textright.png
new file mode 100644 (file)
index 0000000..e7c0464
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textright.png differ
diff --git a/src/designer/components/formeditor/images/mac/textsubscript.png b/src/designer/components/formeditor/images/mac/textsubscript.png
new file mode 100644 (file)
index 0000000..ff431f3
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textsubscript.png differ
diff --git a/src/designer/components/formeditor/images/mac/textsuperscript.png b/src/designer/components/formeditor/images/mac/textsuperscript.png
new file mode 100644 (file)
index 0000000..cb67a33
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textsuperscript.png differ
diff --git a/src/designer/components/formeditor/images/mac/textunder.png b/src/designer/components/formeditor/images/mac/textunder.png
new file mode 100644 (file)
index 0000000..968bac5
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/textunder.png differ
diff --git a/src/designer/components/formeditor/images/mac/undo.png b/src/designer/components/formeditor/images/mac/undo.png
new file mode 100644 (file)
index 0000000..a3bd5e0
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/undo.png differ
diff --git a/src/designer/components/formeditor/images/mac/up.png b/src/designer/components/formeditor/images/mac/up.png
new file mode 100644 (file)
index 0000000..e437312
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/up.png differ
diff --git a/src/designer/components/formeditor/images/mac/widgettool.png b/src/designer/components/formeditor/images/mac/widgettool.png
new file mode 100644 (file)
index 0000000..e1aa353
Binary files /dev/null and b/src/designer/components/formeditor/images/mac/widgettool.png differ
diff --git a/src/designer/components/formeditor/images/minus-16.png b/src/designer/components/formeditor/images/minus-16.png
new file mode 100644 (file)
index 0000000..745b445
Binary files /dev/null and b/src/designer/components/formeditor/images/minus-16.png differ
diff --git a/src/designer/components/formeditor/images/plus-16.png b/src/designer/components/formeditor/images/plus-16.png
new file mode 100644 (file)
index 0000000..ef43788
Binary files /dev/null and b/src/designer/components/formeditor/images/plus-16.png differ
diff --git a/src/designer/components/formeditor/images/prefix-add.png b/src/designer/components/formeditor/images/prefix-add.png
new file mode 100644 (file)
index 0000000..cfbb053
Binary files /dev/null and b/src/designer/components/formeditor/images/prefix-add.png differ
diff --git a/src/designer/components/formeditor/images/qt3logo.png b/src/designer/components/formeditor/images/qt3logo.png
new file mode 100644 (file)
index 0000000..7202850
Binary files /dev/null and b/src/designer/components/formeditor/images/qt3logo.png differ
diff --git a/src/designer/components/formeditor/images/qtlogo.png b/src/designer/components/formeditor/images/qtlogo.png
new file mode 100644 (file)
index 0000000..038fa2c
Binary files /dev/null and b/src/designer/components/formeditor/images/qtlogo.png differ
diff --git a/src/designer/components/formeditor/images/reload.png b/src/designer/components/formeditor/images/reload.png
new file mode 100644 (file)
index 0000000..18c752e
Binary files /dev/null and b/src/designer/components/formeditor/images/reload.png differ
diff --git a/src/designer/components/formeditor/images/resetproperty.png b/src/designer/components/formeditor/images/resetproperty.png
new file mode 100644 (file)
index 0000000..9048252
Binary files /dev/null and b/src/designer/components/formeditor/images/resetproperty.png differ
diff --git a/src/designer/components/formeditor/images/sort.png b/src/designer/components/formeditor/images/sort.png
new file mode 100644 (file)
index 0000000..883bfa9
Binary files /dev/null and b/src/designer/components/formeditor/images/sort.png differ
diff --git a/src/designer/components/formeditor/images/submenu.png b/src/designer/components/formeditor/images/submenu.png
new file mode 100644 (file)
index 0000000..3deb28e
Binary files /dev/null and b/src/designer/components/formeditor/images/submenu.png differ
diff --git a/src/designer/components/formeditor/images/widgets/calendarwidget.png b/src/designer/components/formeditor/images/widgets/calendarwidget.png
new file mode 100644 (file)
index 0000000..26737b8
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/calendarwidget.png differ
diff --git a/src/designer/components/formeditor/images/widgets/checkbox.png b/src/designer/components/formeditor/images/widgets/checkbox.png
new file mode 100644 (file)
index 0000000..ab6f53e
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/checkbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/columnview.png b/src/designer/components/formeditor/images/widgets/columnview.png
new file mode 100644 (file)
index 0000000..4132ee6
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/columnview.png differ
diff --git a/src/designer/components/formeditor/images/widgets/combobox.png b/src/designer/components/formeditor/images/widgets/combobox.png
new file mode 100644 (file)
index 0000000..bf3ed79
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/combobox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/commandlinkbutton.png b/src/designer/components/formeditor/images/widgets/commandlinkbutton.png
new file mode 100644 (file)
index 0000000..6bbd84a
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/commandlinkbutton.png differ
diff --git a/src/designer/components/formeditor/images/widgets/dateedit.png b/src/designer/components/formeditor/images/widgets/dateedit.png
new file mode 100644 (file)
index 0000000..6827fa7
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/dateedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/datetimeedit.png b/src/designer/components/formeditor/images/widgets/datetimeedit.png
new file mode 100644 (file)
index 0000000..7d8e6fe
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/datetimeedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/dial.png b/src/designer/components/formeditor/images/widgets/dial.png
new file mode 100644 (file)
index 0000000..050d1db
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/dial.png differ
diff --git a/src/designer/components/formeditor/images/widgets/dialogbuttonbox.png b/src/designer/components/formeditor/images/widgets/dialogbuttonbox.png
new file mode 100644 (file)
index 0000000..b1f89fb
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/dialogbuttonbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/dockwidget.png b/src/designer/components/formeditor/images/widgets/dockwidget.png
new file mode 100644 (file)
index 0000000..9eee04f
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/dockwidget.png differ
diff --git a/src/designer/components/formeditor/images/widgets/doublespinbox.png b/src/designer/components/formeditor/images/widgets/doublespinbox.png
new file mode 100644 (file)
index 0000000..5686ac8
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/doublespinbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/fontcombobox.png b/src/designer/components/formeditor/images/widgets/fontcombobox.png
new file mode 100644 (file)
index 0000000..6848f15
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/fontcombobox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/frame.png b/src/designer/components/formeditor/images/widgets/frame.png
new file mode 100644 (file)
index 0000000..68f5da0
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/frame.png differ
diff --git a/src/designer/components/formeditor/images/widgets/graphicsview.png b/src/designer/components/formeditor/images/widgets/graphicsview.png
new file mode 100644 (file)
index 0000000..93fe760
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/graphicsview.png differ
diff --git a/src/designer/components/formeditor/images/widgets/groupbox.png b/src/designer/components/formeditor/images/widgets/groupbox.png
new file mode 100644 (file)
index 0000000..4025b4d
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/groupbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/groupboxcollapsible.png b/src/designer/components/formeditor/images/widgets/groupboxcollapsible.png
new file mode 100644 (file)
index 0000000..62fd1ad
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/groupboxcollapsible.png differ
diff --git a/src/designer/components/formeditor/images/widgets/hscrollbar.png b/src/designer/components/formeditor/images/widgets/hscrollbar.png
new file mode 100644 (file)
index 0000000..466c58d
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/hscrollbar.png differ
diff --git a/src/designer/components/formeditor/images/widgets/hslider.png b/src/designer/components/formeditor/images/widgets/hslider.png
new file mode 100644 (file)
index 0000000..525bd1c
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/hslider.png differ
diff --git a/src/designer/components/formeditor/images/widgets/hsplit.png b/src/designer/components/formeditor/images/widgets/hsplit.png
new file mode 100644 (file)
index 0000000..1ea8f2a
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/hsplit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/label.png b/src/designer/components/formeditor/images/widgets/label.png
new file mode 100644 (file)
index 0000000..5d7d7b4
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/label.png differ
diff --git a/src/designer/components/formeditor/images/widgets/lcdnumber.png b/src/designer/components/formeditor/images/widgets/lcdnumber.png
new file mode 100644 (file)
index 0000000..c3cac18
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/lcdnumber.png differ
diff --git a/src/designer/components/formeditor/images/widgets/line.png b/src/designer/components/formeditor/images/widgets/line.png
new file mode 100644 (file)
index 0000000..5c64dfb
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/line.png differ
diff --git a/src/designer/components/formeditor/images/widgets/lineedit.png b/src/designer/components/formeditor/images/widgets/lineedit.png
new file mode 100644 (file)
index 0000000..75fc890
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/lineedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/listbox.png b/src/designer/components/formeditor/images/widgets/listbox.png
new file mode 100644 (file)
index 0000000..367e67f
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/listbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/listview.png b/src/designer/components/formeditor/images/widgets/listview.png
new file mode 100644 (file)
index 0000000..d1308d5
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/listview.png differ
diff --git a/src/designer/components/formeditor/images/widgets/mdiarea.png b/src/designer/components/formeditor/images/widgets/mdiarea.png
new file mode 100644 (file)
index 0000000..7783dd5
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/mdiarea.png differ
diff --git a/src/designer/components/formeditor/images/widgets/plaintextedit.png b/src/designer/components/formeditor/images/widgets/plaintextedit.png
new file mode 100644 (file)
index 0000000..077bf16
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/plaintextedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/progress.png b/src/designer/components/formeditor/images/widgets/progress.png
new file mode 100644 (file)
index 0000000..44ae094
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/progress.png differ
diff --git a/src/designer/components/formeditor/images/widgets/pushbutton.png b/src/designer/components/formeditor/images/widgets/pushbutton.png
new file mode 100644 (file)
index 0000000..61f779c
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/pushbutton.png differ
diff --git a/src/designer/components/formeditor/images/widgets/radiobutton.png b/src/designer/components/formeditor/images/widgets/radiobutton.png
new file mode 100644 (file)
index 0000000..10c1d8c
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/radiobutton.png differ
diff --git a/src/designer/components/formeditor/images/widgets/scrollarea.png b/src/designer/components/formeditor/images/widgets/scrollarea.png
new file mode 100644 (file)
index 0000000..651ea24
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/scrollarea.png differ
diff --git a/src/designer/components/formeditor/images/widgets/spacer.png b/src/designer/components/formeditor/images/widgets/spacer.png
new file mode 100644 (file)
index 0000000..8a0931b
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/spacer.png differ
diff --git a/src/designer/components/formeditor/images/widgets/spinbox.png b/src/designer/components/formeditor/images/widgets/spinbox.png
new file mode 100644 (file)
index 0000000..cdd9fe1
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/spinbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/tabbar.png b/src/designer/components/formeditor/images/widgets/tabbar.png
new file mode 100644 (file)
index 0000000..d5d3783
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/tabbar.png differ
diff --git a/src/designer/components/formeditor/images/widgets/table.png b/src/designer/components/formeditor/images/widgets/table.png
new file mode 100644 (file)
index 0000000..4bbd9c2
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/table.png differ
diff --git a/src/designer/components/formeditor/images/widgets/tabwidget.png b/src/designer/components/formeditor/images/widgets/tabwidget.png
new file mode 100644 (file)
index 0000000..1254bb6
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/tabwidget.png differ
diff --git a/src/designer/components/formeditor/images/widgets/textedit.png b/src/designer/components/formeditor/images/widgets/textedit.png
new file mode 100644 (file)
index 0000000..32e897d
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/textedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/timeedit.png b/src/designer/components/formeditor/images/widgets/timeedit.png
new file mode 100644 (file)
index 0000000..c66d91b
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/timeedit.png differ
diff --git a/src/designer/components/formeditor/images/widgets/toolbox.png b/src/designer/components/formeditor/images/widgets/toolbox.png
new file mode 100644 (file)
index 0000000..2ab71dc
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/toolbox.png differ
diff --git a/src/designer/components/formeditor/images/widgets/toolbutton.png b/src/designer/components/formeditor/images/widgets/toolbutton.png
new file mode 100644 (file)
index 0000000..0bff069
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/toolbutton.png differ
diff --git a/src/designer/components/formeditor/images/widgets/vline.png b/src/designer/components/formeditor/images/widgets/vline.png
new file mode 100644 (file)
index 0000000..35a7300
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/vline.png differ
diff --git a/src/designer/components/formeditor/images/widgets/vscrollbar.png b/src/designer/components/formeditor/images/widgets/vscrollbar.png
new file mode 100644 (file)
index 0000000..28b7c40
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/vscrollbar.png differ
diff --git a/src/designer/components/formeditor/images/widgets/vslider.png b/src/designer/components/formeditor/images/widgets/vslider.png
new file mode 100644 (file)
index 0000000..59f06ba
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/vslider.png differ
diff --git a/src/designer/components/formeditor/images/widgets/vspacer.png b/src/designer/components/formeditor/images/widgets/vspacer.png
new file mode 100644 (file)
index 0000000..ce5e8bd
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/vspacer.png differ
diff --git a/src/designer/components/formeditor/images/widgets/widget.png b/src/designer/components/formeditor/images/widgets/widget.png
new file mode 100644 (file)
index 0000000..1cf960e
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/widget.png differ
diff --git a/src/designer/components/formeditor/images/widgets/widgetstack.png b/src/designer/components/formeditor/images/widgets/widgetstack.png
new file mode 100644 (file)
index 0000000..2c6964e
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/widgetstack.png differ
diff --git a/src/designer/components/formeditor/images/widgets/wizard.png b/src/designer/components/formeditor/images/widgets/wizard.png
new file mode 100644 (file)
index 0000000..7c0e107
Binary files /dev/null and b/src/designer/components/formeditor/images/widgets/wizard.png differ
diff --git a/src/designer/components/formeditor/images/win/adjustsize.png b/src/designer/components/formeditor/images/win/adjustsize.png
new file mode 100644 (file)
index 0000000..3cda333
Binary files /dev/null and b/src/designer/components/formeditor/images/win/adjustsize.png differ
diff --git a/src/designer/components/formeditor/images/win/back.png b/src/designer/components/formeditor/images/win/back.png
new file mode 100644 (file)
index 0000000..e58177f
Binary files /dev/null and b/src/designer/components/formeditor/images/win/back.png differ
diff --git a/src/designer/components/formeditor/images/win/buddytool.png b/src/designer/components/formeditor/images/win/buddytool.png
new file mode 100644 (file)
index 0000000..4cd968b
Binary files /dev/null and b/src/designer/components/formeditor/images/win/buddytool.png differ
diff --git a/src/designer/components/formeditor/images/win/down.png b/src/designer/components/formeditor/images/win/down.png
new file mode 100644 (file)
index 0000000..29d1d44
Binary files /dev/null and b/src/designer/components/formeditor/images/win/down.png differ
diff --git a/src/designer/components/formeditor/images/win/editbreaklayout.png b/src/designer/components/formeditor/images/win/editbreaklayout.png
new file mode 100644 (file)
index 0000000..07c5fae
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editbreaklayout.png differ
diff --git a/src/designer/components/formeditor/images/win/editcopy.png b/src/designer/components/formeditor/images/win/editcopy.png
new file mode 100644 (file)
index 0000000..1121b47
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editcopy.png differ
diff --git a/src/designer/components/formeditor/images/win/editcut.png b/src/designer/components/formeditor/images/win/editcut.png
new file mode 100644 (file)
index 0000000..4b6c82c
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editcut.png differ
diff --git a/src/designer/components/formeditor/images/win/editdelete.png b/src/designer/components/formeditor/images/win/editdelete.png
new file mode 100644 (file)
index 0000000..5a42514
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editdelete.png differ
diff --git a/src/designer/components/formeditor/images/win/editform.png b/src/designer/components/formeditor/images/win/editform.png
new file mode 100644 (file)
index 0000000..452fcd8
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editform.png differ
diff --git a/src/designer/components/formeditor/images/win/editgrid.png b/src/designer/components/formeditor/images/win/editgrid.png
new file mode 100644 (file)
index 0000000..789bf7d
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editgrid.png differ
diff --git a/src/designer/components/formeditor/images/win/edithlayout.png b/src/designer/components/formeditor/images/win/edithlayout.png
new file mode 100644 (file)
index 0000000..4dd3f0c
Binary files /dev/null and b/src/designer/components/formeditor/images/win/edithlayout.png differ
diff --git a/src/designer/components/formeditor/images/win/edithlayoutsplit.png b/src/designer/components/formeditor/images/win/edithlayoutsplit.png
new file mode 100644 (file)
index 0000000..2dcc690
Binary files /dev/null and b/src/designer/components/formeditor/images/win/edithlayoutsplit.png differ
diff --git a/src/designer/components/formeditor/images/win/editlower.png b/src/designer/components/formeditor/images/win/editlower.png
new file mode 100644 (file)
index 0000000..ba63094
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editlower.png differ
diff --git a/src/designer/components/formeditor/images/win/editpaste.png b/src/designer/components/formeditor/images/win/editpaste.png
new file mode 100644 (file)
index 0000000..ffab15a
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editpaste.png differ
diff --git a/src/designer/components/formeditor/images/win/editraise.png b/src/designer/components/formeditor/images/win/editraise.png
new file mode 100644 (file)
index 0000000..bb8362c
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editraise.png differ
diff --git a/src/designer/components/formeditor/images/win/editvlayout.png b/src/designer/components/formeditor/images/win/editvlayout.png
new file mode 100644 (file)
index 0000000..7ad28fd
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editvlayout.png differ
diff --git a/src/designer/components/formeditor/images/win/editvlayoutsplit.png b/src/designer/components/formeditor/images/win/editvlayoutsplit.png
new file mode 100644 (file)
index 0000000..720e18b
Binary files /dev/null and b/src/designer/components/formeditor/images/win/editvlayoutsplit.png differ
diff --git a/src/designer/components/formeditor/images/win/filenew.png b/src/designer/components/formeditor/images/win/filenew.png
new file mode 100644 (file)
index 0000000..af5d122
Binary files /dev/null and b/src/designer/components/formeditor/images/win/filenew.png differ
diff --git a/src/designer/components/formeditor/images/win/fileopen.png b/src/designer/components/formeditor/images/win/fileopen.png
new file mode 100644 (file)
index 0000000..fc6f17e
Binary files /dev/null and b/src/designer/components/formeditor/images/win/fileopen.png differ
diff --git a/src/designer/components/formeditor/images/win/filesave.png b/src/designer/components/formeditor/images/win/filesave.png
new file mode 100644 (file)
index 0000000..8feec99
Binary files /dev/null and b/src/designer/components/formeditor/images/win/filesave.png differ
diff --git a/src/designer/components/formeditor/images/win/forward.png b/src/designer/components/formeditor/images/win/forward.png
new file mode 100644 (file)
index 0000000..34b91f0
Binary files /dev/null and b/src/designer/components/formeditor/images/win/forward.png differ
diff --git a/src/designer/components/formeditor/images/win/insertimage.png b/src/designer/components/formeditor/images/win/insertimage.png
new file mode 100644 (file)
index 0000000..cfab637
Binary files /dev/null and b/src/designer/components/formeditor/images/win/insertimage.png differ
diff --git a/src/designer/components/formeditor/images/win/minus.png b/src/designer/components/formeditor/images/win/minus.png
new file mode 100644 (file)
index 0000000..c0dc274
Binary files /dev/null and b/src/designer/components/formeditor/images/win/minus.png differ
diff --git a/src/designer/components/formeditor/images/win/plus.png b/src/designer/components/formeditor/images/win/plus.png
new file mode 100644 (file)
index 0000000..ecf0589
Binary files /dev/null and b/src/designer/components/formeditor/images/win/plus.png differ
diff --git a/src/designer/components/formeditor/images/win/redo.png b/src/designer/components/formeditor/images/win/redo.png
new file mode 100644 (file)
index 0000000..686ad14
Binary files /dev/null and b/src/designer/components/formeditor/images/win/redo.png differ
diff --git a/src/designer/components/formeditor/images/win/resourceeditortool.png b/src/designer/components/formeditor/images/win/resourceeditortool.png
new file mode 100644 (file)
index 0000000..cc9cb58
Binary files /dev/null and b/src/designer/components/formeditor/images/win/resourceeditortool.png differ
diff --git a/src/designer/components/formeditor/images/win/signalslottool.png b/src/designer/components/formeditor/images/win/signalslottool.png
new file mode 100644 (file)
index 0000000..e80fd1c
Binary files /dev/null and b/src/designer/components/formeditor/images/win/signalslottool.png differ
diff --git a/src/designer/components/formeditor/images/win/simplifyrichtext.png b/src/designer/components/formeditor/images/win/simplifyrichtext.png
new file mode 100644 (file)
index 0000000..e251cf7
Binary files /dev/null and b/src/designer/components/formeditor/images/win/simplifyrichtext.png differ
diff --git a/src/designer/components/formeditor/images/win/tabordertool.png b/src/designer/components/formeditor/images/win/tabordertool.png
new file mode 100644 (file)
index 0000000..7e6e2de
Binary files /dev/null and b/src/designer/components/formeditor/images/win/tabordertool.png differ
diff --git a/src/designer/components/formeditor/images/win/textanchor.png b/src/designer/components/formeditor/images/win/textanchor.png
new file mode 100644 (file)
index 0000000..1911ab0
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textanchor.png differ
diff --git a/src/designer/components/formeditor/images/win/textbold.png b/src/designer/components/formeditor/images/win/textbold.png
new file mode 100644 (file)
index 0000000..9cbc713
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textbold.png differ
diff --git a/src/designer/components/formeditor/images/win/textcenter.png b/src/designer/components/formeditor/images/win/textcenter.png
new file mode 100644 (file)
index 0000000..11efb4b
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textcenter.png differ
diff --git a/src/designer/components/formeditor/images/win/textitalic.png b/src/designer/components/formeditor/images/win/textitalic.png
new file mode 100644 (file)
index 0000000..b30ce14
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textitalic.png differ
diff --git a/src/designer/components/formeditor/images/win/textjustify.png b/src/designer/components/formeditor/images/win/textjustify.png
new file mode 100644 (file)
index 0000000..9de0c88
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textjustify.png differ
diff --git a/src/designer/components/formeditor/images/win/textleft.png b/src/designer/components/formeditor/images/win/textleft.png
new file mode 100644 (file)
index 0000000..16f80bc
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textleft.png differ
diff --git a/src/designer/components/formeditor/images/win/textright.png b/src/designer/components/formeditor/images/win/textright.png
new file mode 100644 (file)
index 0000000..16872df
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textright.png differ
diff --git a/src/designer/components/formeditor/images/win/textsubscript.png b/src/designer/components/formeditor/images/win/textsubscript.png
new file mode 100644 (file)
index 0000000..d86347d
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textsubscript.png differ
diff --git a/src/designer/components/formeditor/images/win/textsuperscript.png b/src/designer/components/formeditor/images/win/textsuperscript.png
new file mode 100644 (file)
index 0000000..9109965
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textsuperscript.png differ
diff --git a/src/designer/components/formeditor/images/win/textunder.png b/src/designer/components/formeditor/images/win/textunder.png
new file mode 100644 (file)
index 0000000..c72eff5
Binary files /dev/null and b/src/designer/components/formeditor/images/win/textunder.png differ
diff --git a/src/designer/components/formeditor/images/win/undo.png b/src/designer/components/formeditor/images/win/undo.png
new file mode 100644 (file)
index 0000000..c3b8c51
Binary files /dev/null and b/src/designer/components/formeditor/images/win/undo.png differ
diff --git a/src/designer/components/formeditor/images/win/up.png b/src/designer/components/formeditor/images/win/up.png
new file mode 100644 (file)
index 0000000..e437312
Binary files /dev/null and b/src/designer/components/formeditor/images/win/up.png differ
diff --git a/src/designer/components/formeditor/images/win/widgettool.png b/src/designer/components/formeditor/images/win/widgettool.png
new file mode 100644 (file)
index 0000000..a52224e
Binary files /dev/null and b/src/designer/components/formeditor/images/win/widgettool.png differ
diff --git a/src/designer/components/formeditor/itemview_propertysheet.cpp b/src/designer/components/formeditor/itemview_propertysheet.cpp
new file mode 100644 (file)
index 0000000..974724d
--- /dev/null
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemview_propertysheet.h"
+
+#include <QtDesigner/abstractformeditor.h>
+
+#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
+#include <moc_itemview_propertysheet.h>
diff --git a/src/designer/components/formeditor/itemview_propertysheet.h b/src/designer/components/formeditor/itemview_propertysheet.h
new file mode 100644 (file)
index 0000000..db6aa56
--- /dev/null
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/layout_propertysheet.cpp b/src/designer/components/formeditor/layout_propertysheet.cpp
new file mode 100644 (file)
index 0000000..c1ff382
--- /dev/null
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "layout_propertysheet.h"
+
+// sdk
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractformeditor.h>
+
+// 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
+#include <moc_layout_propertysheet.h>
diff --git a/src/designer/components/formeditor/layout_propertysheet.h b/src/designer/components/formeditor/layout_propertysheet.h
new file mode 100644 (file)
index 0000000..eab66fb
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/line_propertysheet.cpp b/src/designer/components/formeditor/line_propertysheet.cpp
new file mode 100644 (file)
index 0000000..4d1d4f0
--- /dev/null
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "line_propertysheet.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QLayout>
+#include <QtCore/QMetaObject>
+#include <QtCore/qmetaobject.h>
+#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
+#include <moc_line_propertysheet.h>
diff --git a/src/designer/components/formeditor/line_propertysheet.h b/src/designer/components/formeditor/line_propertysheet.h
new file mode 100644 (file)
index 0000000..cf22265
--- /dev/null
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/previewactiongroup.cpp b/src/designer/components/formeditor/previewactiongroup.cpp
new file mode 100644 (file)
index 0000000..6c35813
--- /dev/null
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_previewactiongroup.h>
diff --git a/src/designer/components/formeditor/previewactiongroup.h b/src/designer/components/formeditor/previewactiongroup.h
new file mode 100644 (file)
index 0000000..0718f8b
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for 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/components/formeditor/qdesigner_resource.cpp b/src/designer/components/formeditor/qdesigner_resource.cpp
new file mode 100644 (file)
index 0000000..3381574
--- /dev/null
@@ -0,0 +1,2475 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/propertysheet.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/extrainfo.h>
+#include <QtDesigner/abstractformwindowtool.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/container.h>
+#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/qwizard.h>
+#include <qlayoutengine_p.h>
+
+#include <QtCore/QBuffer>
+#include <QtCore/QDir>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qxmlstream.h>
+
+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(), 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/components/formeditor/qdesigner_resource.h b/src/designer/components/formeditor/qdesigner_resource.h
new file mode 100644 (file)
index 0000000..ddcd9bb
--- /dev/null
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/qdesignerundostack.cpp b/src/designer/components/formeditor/qdesignerundostack.cpp
new file mode 100644 (file)
index 0000000..508995f
--- /dev/null
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesignerundostack.h"
+
+#include <QtGui/QUndoStack>
+#include <QtGui/qundostack.h>
+
+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
+#include <moc_qdesignerundostack.h>
diff --git a/src/designer/components/formeditor/qdesignerundostack.h b/src/designer/components/formeditor/qdesignerundostack.h
new file mode 100644 (file)
index 0000000..c6a0b35
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/qlayoutwidget_propertysheet.cpp b/src/designer/components/formeditor/qlayoutwidget_propertysheet.cpp
new file mode 100644 (file)
index 0000000..858bdec
--- /dev/null
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_qlayoutwidget_propertysheet.h>
diff --git a/src/designer/components/formeditor/qlayoutwidget_propertysheet.h b/src/designer/components/formeditor/qlayoutwidget_propertysheet.h
new file mode 100644 (file)
index 0000000..8c07470
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/qmainwindow_container.cpp b/src/designer/components/formeditor/qmainwindow_container.cpp
new file mode 100644 (file)
index 0000000..03669e5
--- /dev/null
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_qmainwindow_container.h>
diff --git a/src/designer/components/formeditor/qmainwindow_container.h b/src/designer/components/formeditor/qmainwindow_container.h
new file mode 100644 (file)
index 0000000..40e25c3
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMAINWINDOW_CONTAINER_H
+#define QMAINWINDOW_CONTAINER_H
+
+#include <QtDesigner/container.h>
+#include <QtDesigner/default_extensionfactory.h>
+
+#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/components/formeditor/qmdiarea_container.cpp b/src/designer/components/formeditor/qmdiarea_container.cpp
new file mode 100644 (file)
index 0000000..77166c7
--- /dev/null
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmdiarea_container.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractformeditor.h>
+
+#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
+#include <moc_qmdiarea_container.h>
diff --git a/src/designer/components/formeditor/qmdiarea_container.h b/src/designer/components/formeditor/qmdiarea_container.h
new file mode 100644 (file)
index 0000000..ec44dbf
--- /dev/null
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMDIAREA_CONTAINER_H
+#define QMDIAREA_CONTAINER_H
+
+#include <QtDesigner/container.h>
+
+
+#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/components/formeditor/qtbrushmanager.cpp b/src/designer/components/formeditor/qtbrushmanager.cpp
new file mode 100644 (file)
index 0000000..de06f12
--- /dev/null
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_qtbrushmanager.h>
diff --git a/src/designer/components/formeditor/qtbrushmanager.h b/src/designer/components/formeditor/qtbrushmanager.h
new file mode 100644 (file)
index 0000000..025927a
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTBRUSHMANAGER_H
+#define QTBRUSHMANAGER_H
+
+#include <QtDesigner/abstractbrushmanager.h>
+#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/components/formeditor/qwizard_container.cpp b/src/designer/components/formeditor/qwizard_container.cpp
new file mode 100644 (file)
index 0000000..9d7fb18
--- /dev/null
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwizard_container.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractformeditor.h>
+
+#include <QtGui/QWizard>
+#include <QtGui/qwizard.h>
+#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
+#include <moc_qwizard_container.h>
diff --git a/src/designer/components/formeditor/qwizard_container.h b/src/designer/components/formeditor/qwizard_container.h
new file mode 100644 (file)
index 0000000..12397a6
--- /dev/null
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIZARD_CONTAINER_H
+#define QWIZARD_CONTAINER_H
+
+#include <QtDesigner/container.h>
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QWizard>
+#include <QtGui/qwizard.h>
+
+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/components/formeditor/qworkspace_container.cpp b/src/designer/components/formeditor/qworkspace_container.cpp
new file mode 100644 (file)
index 0000000..e299ba4
--- /dev/null
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_qworkspace_container.h>
diff --git a/src/designer/components/formeditor/qworkspace_container.h b/src/designer/components/formeditor/qworkspace_container.h
new file mode 100644 (file)
index 0000000..a1e534a
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWORKSPACE_CONTAINER_H
+#define QWORKSPACE_CONTAINER_H
+
+#include <QtDesigner/container.h>
+#include <QtDesigner/default_extensionfactory.h>
+
+#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/components/formeditor/spacer_propertysheet.cpp b/src/designer/components/formeditor/spacer_propertysheet.cpp
new file mode 100644 (file)
index 0000000..981e7a6
--- /dev/null
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_spacer_propertysheet.h>
diff --git a/src/designer/components/formeditor/spacer_propertysheet.h b/src/designer/components/formeditor/spacer_propertysheet.h
new file mode 100644 (file)
index 0000000..eebac63
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/formeditor/templateoptionspage.cpp b/src/designer/components/formeditor/templateoptionspage.cpp
new file mode 100644 (file)
index 0000000..a89ab12
--- /dev/null
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "templateoptionspage.h"
+#include "ui_templateoptionspage.h"
+
+#include <shared_settings_p.h>
+#include <iconloader_p.h>
+
+#include <QtDesigner/abstractformeditor.h>
+#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
+
+#include "moc_templateoptionspage.h"
diff --git a/src/designer/components/formeditor/templateoptionspage.h b/src/designer/components/formeditor/templateoptionspage.h
new file mode 100644 (file)
index 0000000..41f2cdc
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_TEMPLATEOPTIONS_H
+#define QDESIGNER_TEMPLATEOPTIONS_H
+
+#include <QtDesigner/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/components/formeditor/templateoptionspage.ui b/src/designer/components/formeditor/templateoptionspage.ui
new file mode 100644 (file)
index 0000000..3427ffe
--- /dev/null
@@ -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/components/formeditor/tool_widgeteditor.cpp b/src/designer/components/formeditor/tool_widgeteditor.cpp
new file mode 100644 (file)
index 0000000..6fcd17a
--- /dev/null
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tool_widgeteditor.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractwidgetfactory.h>
+#include <QtDesigner/abstractwidgetbox.h>
+
+#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
+#include <moc_tool_widgeteditor.h>
diff --git a/src/designer/components/formeditor/tool_widgeteditor.h b/src/designer/components/formeditor/tool_widgeteditor.h
new file mode 100644 (file)
index 0000000..bc7e9a6
--- /dev/null
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOL_WIDGETEDITOR_H
+#define TOOL_WIDGETEDITOR_H
+
+#include <QtDesigner/abstractformwindowtool.h>
+
+#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/components/formeditor/widgetselection.cpp b/src/designer/components/formeditor/widgetselection.cpp
new file mode 100644 (file)
index 0000000..81f5ce7
--- /dev/null
@@ -0,0 +1,745 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetselection.h"
+#include "formwindow.h"
+#include "formwindowmanager.h"
+
+// sdk
+#include <QtDesigner/abstractformeditor.h>
+#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/qevent.h>
+#include <QtGui/QStylePainter>
+#include <QtGui/QGridLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/qstyleoption.h>
+#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 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
+#include <moc_widgetselection.h>
diff --git a/src/designer/components/formeditor/widgetselection.h b/src/designer/components/formeditor/widgetselection.h
new file mode 100644 (file)
index 0000000..3d90b3a
--- /dev/null
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/objectinspector/objectinspector.cmake b/src/designer/components/objectinspector/objectinspector.cmake
new file mode 100644 (file)
index 0000000..0eb56ba
--- /dev/null
@@ -0,0 +1,13 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector/objectinspector.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector/objectinspectormodel_p.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector/objectinspector_global.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector/objectinspector.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/objectinspector/objectinspectormodel.cpp
+)
+
diff --git a/src/designer/components/objectinspector/objectinspector.cpp b/src/designer/components/objectinspector/objectinspector.cpp
new file mode 100644 (file)
index 0000000..4357433
--- /dev/null
@@ -0,0 +1,836 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "objectinspector.h"
+#include "objectinspectormodel_p.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/taskmenu.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractformwindowcursor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/container.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/abstractpropertyeditor.h>
+
+// 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) && !qobject_cast<QMainWindow *>(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
+}
+}
+#include <moc_objectinspector.h>
diff --git a/src/designer/components/objectinspector/objectinspector.h b/src/designer/components/objectinspector/objectinspector.h
new file mode 100644 (file)
index 0000000..194108d
--- /dev/null
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/objectinspector/objectinspector_global.h b/src/designer/components/objectinspector/objectinspector_global.h
new file mode 100644 (file)
index 0000000..e9b1abb
--- /dev/null
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/objectinspector/objectinspectormodel.cpp b/src/designer/components/objectinspector/objectinspectormodel.cpp
new file mode 100644 (file)
index 0000000..80dc048
--- /dev/null
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractwidgetdatabase.h>
+#include <QtDesigner/container.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#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.cacheKey() == i2.cacheKey();
+}
+
+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/components/objectinspector/objectinspectormodel_p.h b/src/designer/components/objectinspector/objectinspectormodel_p.h
new file mode 100644 (file)
index 0000000..9e2be1c
--- /dev/null
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for 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/qabstractitemmodel.h>
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtCore/qmap.h>
+#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/components/propertyeditor/brushpropertymanager.cpp b/src/designer/components/propertyeditor/brushpropertymanager.cpp
new file mode 100644 (file)
index 0000000..8abd9aa
--- /dev/null
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/brushpropertymanager.h b/src/designer/components/propertyeditor/brushpropertymanager.h
new file mode 100644 (file)
index 0000000..b8980f5
--- /dev/null
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/designerpropertymanager.cpp b/src/designer/components/propertyeditor/designerpropertymanager.cpp
new file mode 100644 (file)
index 0000000..48bb1db
--- /dev/null
@@ -0,0 +1,2837 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstracticoncache.h>
+
+#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/qevent.h>
+#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 "moc_designerpropertymanager.cpp"
+#include <moc_designerpropertymanager.h>
diff --git a/src/designer/components/propertyeditor/designerpropertymanager.h b/src/designer/components/propertyeditor/designerpropertymanager.h
new file mode 100644 (file)
index 0000000..b521a59
--- /dev/null
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/fontmapping.xml b/src/designer/components/propertyeditor/fontmapping.xml
new file mode 100644 (file)
index 0000000..1d00832
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $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/components/propertyeditor/fontpropertymanager.cpp b/src/designer/components/propertyeditor/fontpropertymanager.cpp
new file mode 100644 (file)
index 0000000..8dc2562
--- /dev/null
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/fontpropertymanager.h b/src/designer/components/propertyeditor/fontpropertymanager.h
new file mode 100644 (file)
index 0000000..0bb8d67
--- /dev/null
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/newdynamicpropertydialog.cpp b/src/designer/components/propertyeditor/newdynamicpropertydialog.cpp
new file mode 100644 (file)
index 0000000..dee350d
--- /dev/null
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_newdynamicpropertydialog.h>
diff --git a/src/designer/components/propertyeditor/newdynamicpropertydialog.h b/src/designer/components/propertyeditor/newdynamicpropertydialog.h
new file mode 100644 (file)
index 0000000..ad1e96b
--- /dev/null
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/newdynamicpropertydialog.ui b/src/designer/components/propertyeditor/newdynamicpropertydialog.ui
new file mode 100644 (file)
index 0000000..2aa91f3
--- /dev/null
@@ -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/components/propertyeditor/paletteeditor.cpp b/src/designer/components/propertyeditor/paletteeditor.cpp
new file mode 100644 (file)
index 0000000..a0e3f35
--- /dev/null
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "paletteeditor.h"
+
+#include <iconloader_p.h>
+#include <qtcolorbutton.h>
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/abstracticoncache.h>
+
+#include <QtCore/qmetaobject.h>
+#include <QtGui/QPainter>
+#include <QtGui/QToolButton>
+#include <QtGui/QLabel>
+#include <QtGui/QHeaderView>
+#include <QtGui/qpen.h>
+
+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
+#include <moc_paletteeditor.h>
diff --git a/src/designer/components/propertyeditor/paletteeditor.h b/src/designer/components/propertyeditor/paletteeditor.h
new file mode 100644 (file)
index 0000000..c752093
--- /dev/null
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/paletteeditor.ui b/src/designer/components/propertyeditor/paletteeditor.ui
new file mode 100644 (file)
index 0000000..d78972a
--- /dev/null
@@ -0,0 +1,264 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/paletteeditorbutton.cpp b/src/designer/components/propertyeditor/paletteeditorbutton.cpp
new file mode 100644 (file)
index 0000000..b0437ae
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_paletteeditorbutton.h>
diff --git a/src/designer/components/propertyeditor/paletteeditorbutton.h b/src/designer/components/propertyeditor/paletteeditorbutton.h
new file mode 100644 (file)
index 0000000..21285d4
--- /dev/null
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/previewframe.cpp b/src/designer/components/propertyeditor/previewframe.cpp
new file mode 100644 (file)
index 0000000..3a61886
--- /dev/null
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/qevent.h>
+
+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
+#include <moc_previewframe.h>
diff --git a/src/designer/components/propertyeditor/previewframe.h b/src/designer/components/propertyeditor/previewframe.h
new file mode 100644 (file)
index 0000000..17808a8
--- /dev/null
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/previewwidget.cpp b/src/designer/components/propertyeditor/previewwidget.cpp
new file mode 100644 (file)
index 0000000..c01256d
--- /dev/null
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_previewwidget.h>
diff --git a/src/designer/components/propertyeditor/previewwidget.h b/src/designer/components/propertyeditor/previewwidget.h
new file mode 100644 (file)
index 0000000..c90cefa
--- /dev/null
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/previewwidget.ui b/src/designer/components/propertyeditor/previewwidget.ui
new file mode 100644 (file)
index 0000000..e09c048
--- /dev/null
@@ -0,0 +1,238 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/propertyeditor.cmake b/src/designer/components/propertyeditor/propertyeditor.cmake
new file mode 100644 (file)
index 0000000..1ece255
--- /dev/null
@@ -0,0 +1,38 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/propertyeditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/designerpropertymanager.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/paletteeditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/paletteeditorbutton.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/stringlisteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/stringlisteditorbutton.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/previewwidget.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/previewframe.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/newdynamicpropertydialog.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/brushpropertymanager.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/fontpropertymanager.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/propertyeditor_global.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/qlonglongvalidator.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/propertyeditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/designerpropertymanager.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/paletteeditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/paletteeditorbutton.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/stringlisteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/stringlisteditorbutton.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/previewwidget.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/previewframe.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/newdynamicpropertydialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/brushpropertymanager.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/fontpropertymanager.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/qlonglongvalidator.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/propertyeditor.qrc
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/paletteeditor.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/stringlisteditor.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/previewwidget.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/propertyeditor/newdynamicpropertydialog.ui
+)
+
diff --git a/src/designer/components/propertyeditor/propertyeditor.cpp b/src/designer/components/propertyeditor/propertyeditor.cpp
new file mode 100644 (file)
index 0000000..f3fb13c
--- /dev/null
@@ -0,0 +1,1297 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/abstractwidgetdatabase.h>
+#include <QtDesigner/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
+
+#include <moc_propertyeditor.h>
+#include <qrc_propertyeditor.cpp>
diff --git a/src/designer/components/propertyeditor/propertyeditor.h b/src/designer/components/propertyeditor/propertyeditor.h
new file mode 100644 (file)
index 0000000..49a998d
--- /dev/null
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/propertyeditor.qrc b/src/designer/components/propertyeditor/propertyeditor.qrc
new file mode 100644 (file)
index 0000000..68008ec
--- /dev/null
@@ -0,0 +1,5 @@
+<RCC>
+  <qresource prefix="/trolltech/propertyeditor">
+    <file>fontmapping.xml</file>
+  </qresource>
+</RCC>
diff --git a/src/designer/components/propertyeditor/propertyeditor_global.h b/src/designer/components/propertyeditor/propertyeditor_global.h
new file mode 100644 (file)
index 0000000..1d048d4
--- /dev/null
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/qlonglongvalidator.cpp b/src/designer/components/propertyeditor/qlonglongvalidator.cpp
new file mode 100644 (file)
index 0000000..bac55d9
--- /dev/null
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_qlonglongvalidator.h>
diff --git a/src/designer/components/propertyeditor/qlonglongvalidator.h b/src/designer/components/propertyeditor/qlonglongvalidator.h
new file mode 100644 (file)
index 0000000..e814105
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/stringlisteditor.cpp b/src/designer/components/propertyeditor/stringlisteditor.cpp
new file mode 100644 (file)
index 0000000..1280a68
--- /dev/null
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_stringlisteditor.h>
diff --git a/src/designer/components/propertyeditor/stringlisteditor.h b/src/designer/components/propertyeditor/stringlisteditor.h
new file mode 100644 (file)
index 0000000..d7a748d
--- /dev/null
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/stringlisteditor.ui b/src/designer/components/propertyeditor/stringlisteditor.ui
new file mode 100644 (file)
index 0000000..8c9e5ee
--- /dev/null
@@ -0,0 +1,265 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/propertyeditor/stringlisteditorbutton.cpp b/src/designer/components/propertyeditor/stringlisteditorbutton.cpp
new file mode 100644 (file)
index 0000000..32b3498
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+#include <moc_stringlisteditorbutton.h>
diff --git a/src/designer/components/propertyeditor/stringlisteditorbutton.h b/src/designer/components/propertyeditor/stringlisteditorbutton.h
new file mode 100644 (file)
index 0000000..d3ffb9b
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/qdesigner_components.cpp b/src/designer/components/qdesigner_components.cpp
new file mode 100644 (file)
index 0000000..5e67919
--- /dev/null
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/qdesigner_components.h>
+
+#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/abstractlanguage.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractresourcebrowser.h>
+
+#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/components/signalsloteditor/connectdialog.cpp b/src/designer/components/signalsloteditor/connectdialog.cpp
new file mode 100644 (file)
index 0000000..268297b
--- /dev/null
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "connectdialog_p.h"
+#include "signalslot_utils_p.h"
+
+#include <signalslotdialog_p.h>
+#include <metadatabase_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractwidgetdatabase.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractlanguage.h>
+
+#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
+#include <moc_connectdialog_p.h>
diff --git a/src/designer/components/signalsloteditor/connectdialog.ui b/src/designer/components/signalsloteditor/connectdialog.ui
new file mode 100644 (file)
index 0000000..568516a
--- /dev/null
@@ -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/components/signalsloteditor/connectdialog_p.h b/src/designer/components/signalsloteditor/connectdialog_p.h
new file mode 100644 (file)
index 0000000..dbb9bd2
--- /dev/null
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/signalsloteditor/signalslot_utils.cpp b/src/designer/components/signalsloteditor/signalslot_utils.cpp
new file mode 100644 (file)
index 0000000..45a5df7
--- /dev/null
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalslot_utils_p.h"
+
+#include <qdesigner_membersheet_p.h>
+#include <widgetdatabase_p.h>
+#include <metadatabase_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/abstractlanguage.h>
+
+#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/components/signalsloteditor/signalslot_utils_p.h b/src/designer/components/signalsloteditor/signalslot_utils_p.h
new file mode 100644 (file)
index 0000000..4c96133
--- /dev/null
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/signalsloteditor/signalsloteditor.cmake b/src/designer/components/signalsloteditor/signalsloteditor.cmake
new file mode 100644 (file)
index 0000000..1bc083d
--- /dev/null
@@ -0,0 +1,24 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalslot_utils_p.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/connectdialog_p.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_tool.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_plugin.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_global.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_p.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditorwindow.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalslot_utils.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/connectdialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_tool.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_plugin.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditor_instance.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/signalsloteditorwindow.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/signalsloteditor/connectdialog.ui
+)
+
diff --git a/src/designer/components/signalsloteditor/signalsloteditor.cpp b/src/designer/components/signalsloteditor/signalsloteditor.cpp
new file mode 100644 (file)
index 0000000..17814c3
--- /dev/null
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractmetadatabase.h>
+
+#include <QtGui/QApplication>
+#include <QtGui/qundostack.h>
+#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
+#include <moc_signalsloteditor_p.h>
+#include <moc_signalsloteditor.h>
diff --git a/src/designer/components/signalsloteditor/signalsloteditor.h b/src/designer/components/signalsloteditor/signalsloteditor.h
new file mode 100644 (file)
index 0000000..76a8e4f
--- /dev/null
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_H
+#define SIGNALSLOTEDITOR_H
+
+#include "signalsloteditor_global.h"
+
+#include <QtDesigner/connectionedit_p.h>
+
+#include <QtXml/qdom.h>
+#include <QtXml/qdom.h>
+
+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/components/signalsloteditor/signalsloteditor_global.h b/src/designer/components/signalsloteditor/signalsloteditor_global.h
new file mode 100644 (file)
index 0000000..4f4893e
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/signalsloteditor/signalsloteditor_instance.cpp b/src/designer/components/signalsloteditor/signalsloteditor_instance.cpp
new file mode 100644 (file)
index 0000000..3c974d6
--- /dev/null
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/signalsloteditor/signalsloteditor_p.h b/src/designer/components/signalsloteditor/signalsloteditor_p.h
new file mode 100644 (file)
index 0000000..c897622
--- /dev/null
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/signalsloteditor/signalsloteditor_plugin.cpp b/src/designer/components/signalsloteditor/signalsloteditor_plugin.cpp
new file mode 100644 (file)
index 0000000..111eb5f
--- /dev/null
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalsloteditor_plugin.h"
+#include "signalsloteditor_tool.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+#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
+#include <moc_signalsloteditor_plugin.h>
diff --git a/src/designer/components/signalsloteditor/signalsloteditor_plugin.h b/src/designer/components/signalsloteditor/signalsloteditor_plugin.h
new file mode 100644 (file)
index 0000000..58398a2
--- /dev/null
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_PLUGIN_H
+#define SIGNALSLOTEDITOR_PLUGIN_H
+
+#include "signalsloteditor_global.h"
+
+#include <QtDesigner/abstractformeditorplugin.h>
+
+#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/components/signalsloteditor/signalsloteditor_tool.cpp b/src/designer/components/signalsloteditor/signalsloteditor_tool.cpp
new file mode 100644 (file)
index 0000000..04517bc
--- /dev/null
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalsloteditor_tool.h"
+#include "signalsloteditor.h"
+#include "ui4_p.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_signalsloteditor_tool.h>
diff --git a/src/designer/components/signalsloteditor/signalsloteditor_tool.h b/src/designer/components/signalsloteditor/signalsloteditor_tool.h
new file mode 100644 (file)
index 0000000..ba5c813
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_TOOL_H
+#define SIGNALSLOTEDITOR_TOOL_H
+
+#include "signalsloteditor_global.h"
+#include "signalsloteditor.h"
+
+#include <QtCore/QPointer>
+#include <QtDesigner/abstractformwindowtool.h>
+
+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/components/signalsloteditor/signalsloteditorwindow.cpp b/src/designer/components/signalsloteditor/signalsloteditorwindow.cpp
new file mode 100644 (file)
index 0000000..8d684d1
--- /dev/null
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/container.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/abstractformwindowcursor.h>
+#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 "moc_signalsloteditorwindow.cpp"
+#include <moc_signalsloteditorwindow.h>
diff --git a/src/designer/components/signalsloteditor/signalsloteditorwindow.h b/src/designer/components/signalsloteditor/signalsloteditorwindow.h
new file mode 100644 (file)
index 0000000..a1f8bff
--- /dev/null
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/tabordereditor/tabordereditor.cmake b/src/designer/components/tabordereditor/tabordereditor.cmake
new file mode 100644 (file)
index 0000000..b74b565
--- /dev/null
@@ -0,0 +1,15 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_plugin.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_tool.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_global.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_tool.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_plugin.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/tabordereditor/tabordereditor_instance.cpp
+)
diff --git a/src/designer/components/tabordereditor/tabordereditor.cpp b/src/designer/components/tabordereditor/tabordereditor.cpp
new file mode 100644 (file)
index 0000000..926cec5
--- /dev/null
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowcursor.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractwidgetfactory.h>
+#include <QtDesigner/propertysheet.h>
+
+#include <QtGui/QPainter>
+#include <QtGui/qevent.h>
+#include <QtGui/qevent.h>
+#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::TabFocus);
+        }
+    }
+
+    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
+#include <moc_tabordereditor.h>
diff --git a/src/designer/components/tabordereditor/tabordereditor.h b/src/designer/components/tabordereditor/tabordereditor.h
new file mode 100644 (file)
index 0000000..9487ee0
--- /dev/null
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/tabordereditor/tabordereditor_global.h b/src/designer/components/tabordereditor/tabordereditor_global.h
new file mode 100644 (file)
index 0000000..7f6bbde
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/tabordereditor/tabordereditor_instance.cpp b/src/designer/components/tabordereditor/tabordereditor_instance.cpp
new file mode 100644 (file)
index 0000000..2c386ad
--- /dev/null
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/tabordereditor/tabordereditor_plugin.cpp b/src/designer/components/tabordereditor/tabordereditor_plugin.cpp
new file mode 100644 (file)
index 0000000..53cce64
--- /dev/null
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QAction>
+
+#include "tabordereditor_plugin.h"
+#include "tabordereditor_tool.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+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
+#include <moc_tabordereditor_plugin.h>
diff --git a/src/designer/components/tabordereditor/tabordereditor_plugin.h b/src/designer/components/tabordereditor/tabordereditor_plugin.h
new file mode 100644 (file)
index 0000000..451686a
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_PLUGIN_H
+#define TABORDEREDITOR_PLUGIN_H
+
+#include "tabordereditor_global.h"
+
+#include <QtDesigner/abstractformeditorplugin.h>
+
+#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/components/tabordereditor/tabordereditor_tool.cpp b/src/designer/components/tabordereditor/tabordereditor_tool.cpp
new file mode 100644 (file)
index 0000000..47a8e4d
--- /dev/null
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tabordereditor_tool.h"
+#include "tabordereditor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_tabordereditor_tool.h>
diff --git a/src/designer/components/tabordereditor/tabordereditor_tool.h b/src/designer/components/tabordereditor/tabordereditor_tool.h
new file mode 100644 (file)
index 0000000..cb8a1df
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_TOOL_H
+#define TABORDEREDITOR_TOOL_H
+
+#include "tabordereditor_global.h"
+
+#include <QtCore/QPointer>
+
+#include <QtDesigner/abstractformwindowtool.h>
+
+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/components/taskmenu/button_taskmenu.cpp b/src/designer/components/taskmenu/button_taskmenu.cpp
new file mode 100644 (file)
index 0000000..92034c2
--- /dev/null
@@ -0,0 +1,710 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "button_taskmenu.h"
+#include "inplace_editor.h"
+#include <qdesigner_formwindowcommand_p.h>
+#include <formwindowbase_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowcursor.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/abstractobjectinspector.h>
+#include <QtDesigner/abstractpropertyeditor.h>
+
+#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
+#include <moc_button_taskmenu.h>
diff --git a/src/designer/components/taskmenu/button_taskmenu.h b/src/designer/components/taskmenu/button_taskmenu.h
new file mode 100644 (file)
index 0000000..a6ddc93
--- /dev/null
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/combobox_taskmenu.cpp b/src/designer/components/taskmenu/combobox_taskmenu.cpp
new file mode 100644 (file)
index 0000000..8e8759b
--- /dev/null
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "combobox_taskmenu.h"
+#include "listwidgeteditor.h"
+#include "qdesigner_utils_p.h"
+#include <qdesigner_command_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_combobox_taskmenu.h>
diff --git a/src/designer/components/taskmenu/combobox_taskmenu.h b/src/designer/components/taskmenu/combobox_taskmenu.h
new file mode 100644 (file)
index 0000000..2b7ac76
--- /dev/null
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/containerwidget_taskmenu.cpp b/src/designer/components/taskmenu/containerwidget_taskmenu.cpp
new file mode 100644 (file)
index 0000000..9da59e4
--- /dev/null
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "containerwidget_taskmenu.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/container.h>
+
+#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
+#include <moc_containerwidget_taskmenu.h>
diff --git a/src/designer/components/taskmenu/containerwidget_taskmenu.h b/src/designer/components/taskmenu/containerwidget_taskmenu.h
new file mode 100644 (file)
index 0000000..99dfa34
--- /dev/null
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/groupbox_taskmenu.cpp b/src/designer/components/taskmenu/groupbox_taskmenu.cpp
new file mode 100644 (file)
index 0000000..3c63b96
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "groupbox_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_groupbox_taskmenu.h>
diff --git a/src/designer/components/taskmenu/groupbox_taskmenu.h b/src/designer/components/taskmenu/groupbox_taskmenu.h
new file mode 100644 (file)
index 0000000..8224e14
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/inplace_editor.cpp b/src/designer/components/taskmenu/inplace_editor.cpp
new file mode 100644 (file)
index 0000000..a6ca600
--- /dev/null
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindow.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowcursor.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractlanguage.h>
+#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
+#include <moc_inplace_editor.h>
diff --git a/src/designer/components/taskmenu/inplace_editor.h b/src/designer/components/taskmenu/inplace_editor.h
new file mode 100644 (file)
index 0000000..1093449
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/inplace_widget_helper.cpp b/src/designer/components/taskmenu/inplace_widget_helper.cpp
new file mode 100644 (file)
index 0000000..c7f6323
--- /dev/null
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindow.h"
+#include "inplace_widget_helper.h"
+
+#include <QtGui/qevent.h>
+#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()
+    {
+        if (m_parentWidget)
+            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
+#include <moc_inplace_widget_helper.h>
diff --git a/src/designer/components/taskmenu/inplace_widget_helper.h b/src/designer/components/taskmenu/inplace_widget_helper.h
new file mode 100644 (file)
index 0000000..2c1f329
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INPLACE_WIDGETHELPER_H
+#define INPLACE_WIDGETHELPER_H
+
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QSize>
+#include <QtCore/QPointer>
+#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;
+        QPointer<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/components/taskmenu/itemlisteditor.cpp b/src/designer/components/taskmenu/itemlisteditor.cpp
new file mode 100644 (file)
index 0000000..787b4f4
--- /dev/null
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemlisteditor.h"
+#include <abstractformbuilder.h>
+#include <iconloader_p.h>
+#include <formwindowbase_p.h>
+#include <designerpropertymanager.h>
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_itemlisteditor.h>
diff --git a/src/designer/components/taskmenu/itemlisteditor.h b/src/designer/components/taskmenu/itemlisteditor.h
new file mode 100644 (file)
index 0000000..96c81f5
--- /dev/null
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/itemlisteditor.ui b/src/designer/components/taskmenu/itemlisteditor.ui
new file mode 100644 (file)
index 0000000..89d61db
--- /dev/null
@@ -0,0 +1,156 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/label_taskmenu.cpp b/src/designer/components/taskmenu/label_taskmenu.cpp
new file mode 100644 (file)
index 0000000..82a08e4
--- /dev/null
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "label_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_label_taskmenu.h>
diff --git a/src/designer/components/taskmenu/label_taskmenu.h b/src/designer/components/taskmenu/label_taskmenu.h
new file mode 100644 (file)
index 0000000..3e54540
--- /dev/null
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/layouttaskmenu.cpp b/src/designer/components/taskmenu/layouttaskmenu.cpp
new file mode 100644 (file)
index 0000000..92d5a15
--- /dev/null
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "layouttaskmenu.h"
+#include <formlayoutmenu_p.h>
+#include <morphmenu_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+
+#include <moc_layouttaskmenu.h>
diff --git a/src/designer/components/taskmenu/layouttaskmenu.h b/src/designer/components/taskmenu/layouttaskmenu.h
new file mode 100644 (file)
index 0000000..de614c4
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LAYOUTTASKMENU_H
+#define LAYOUTTASKMENU_H
+
+#include <QtDesigner/taskmenu.h>
+
+#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/components/taskmenu/lineedit_taskmenu.cpp b/src/designer/components/taskmenu/lineedit_taskmenu.cpp
new file mode 100644 (file)
index 0000000..4602a2a
--- /dev/null
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "lineedit_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_lineedit_taskmenu.h>
diff --git a/src/designer/components/taskmenu/lineedit_taskmenu.h b/src/designer/components/taskmenu/lineedit_taskmenu.h
new file mode 100644 (file)
index 0000000..28005da
--- /dev/null
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/listwidget_taskmenu.cpp b/src/designer/components/taskmenu/listwidget_taskmenu.cpp
new file mode 100644 (file)
index 0000000..37483b4
--- /dev/null
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "listwidget_taskmenu.h"
+#include "listwidgeteditor.h"
+#include "qdesigner_utils_p.h"
+#include <qdesigner_command_p.h>
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_listwidget_taskmenu.h>
diff --git a/src/designer/components/taskmenu/listwidget_taskmenu.h b/src/designer/components/taskmenu/listwidget_taskmenu.h
new file mode 100644 (file)
index 0000000..6f7cbb4
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/listwidgeteditor.cpp b/src/designer/components/taskmenu/listwidgeteditor.cpp
new file mode 100644 (file)
index 0000000..28b87f7
--- /dev/null
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "listwidgeteditor.h"
+#include <designerpropertymanager.h>
+#include <abstractformbuilder.h>
+
+#include <QtDesigner/abstractsettings_p.h>
+#include <QtDesigner/abstractformeditor.h>
+
+#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
+#include <moc_listwidgeteditor.h>
diff --git a/src/designer/components/taskmenu/listwidgeteditor.h b/src/designer/components/taskmenu/listwidgeteditor.h
new file mode 100644 (file)
index 0000000..835a989
--- /dev/null
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/menutaskmenu.cpp b/src/designer/components/taskmenu/menutaskmenu.cpp
new file mode 100644 (file)
index 0000000..e859f31
--- /dev/null
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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
+
+#include <moc_menutaskmenu.h>
diff --git a/src/designer/components/taskmenu/menutaskmenu.h b/src/designer/components/taskmenu/menutaskmenu.h
new file mode 100644 (file)
index 0000000..fb34891
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MENUTASKMENU_H
+#define MENUTASKMENU_H
+
+#include <QtDesigner/taskmenu.h>
+
+#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/components/taskmenu/tablewidget_taskmenu.cpp b/src/designer/components/taskmenu/tablewidget_taskmenu.cpp
new file mode 100644 (file)
index 0000000..ce6a283
--- /dev/null
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tablewidget_taskmenu.h"
+#include "tablewidgeteditor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_tablewidget_taskmenu.h>
diff --git a/src/designer/components/taskmenu/tablewidget_taskmenu.h b/src/designer/components/taskmenu/tablewidget_taskmenu.h
new file mode 100644 (file)
index 0000000..bbd728e
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/tablewidgeteditor.cpp b/src/designer/components/taskmenu/tablewidgeteditor.cpp
new file mode 100644 (file)
index 0000000..15597c8
--- /dev/null
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstracticoncache.h>
+#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
+#include <moc_tablewidgeteditor.h>
diff --git a/src/designer/components/taskmenu/tablewidgeteditor.h b/src/designer/components/taskmenu/tablewidgeteditor.h
new file mode 100644 (file)
index 0000000..97ee6bc
--- /dev/null
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/tablewidgeteditor.ui b/src/designer/components/taskmenu/tablewidgeteditor.ui
new file mode 100644 (file)
index 0000000..87400c3
--- /dev/null
@@ -0,0 +1,157 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/taskmenu.cmake b/src/designer/components/taskmenu/taskmenu.cmake
new file mode 100644 (file)
index 0000000..5436511
--- /dev/null
@@ -0,0 +1,51 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/button_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/groupbox_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/label_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/lineedit_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/listwidget_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/treewidget_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/tablewidget_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/combobox_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/textedit_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/toolbar_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/containerwidget_taskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/inplace_editor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/taskmenu_component.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/itemlisteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/listwidgeteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/treewidgeteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/tablewidgeteditor.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/inplace_widget_helper.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/menutaskmenu.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/layouttaskmenu.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/button_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/groupbox_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/label_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/lineedit_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/listwidget_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/treewidget_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/tablewidget_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/combobox_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/textedit_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/toolbar_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/containerwidget_taskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/inplace_editor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/taskmenu_component.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/itemlisteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/listwidgeteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/treewidgeteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/tablewidgeteditor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/inplace_widget_helper.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/menutaskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/layouttaskmenu.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/itemlisteditor.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/treewidgeteditor.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/taskmenu/tablewidgeteditor.ui
+)
+
diff --git a/src/designer/components/taskmenu/taskmenu_component.cpp b/src/designer/components/taskmenu/taskmenu_component.cpp
new file mode 100644 (file)
index 0000000..45a2be9
--- /dev/null
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#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
+
+#include <moc_taskmenu_component.h>
diff --git a/src/designer/components/taskmenu/taskmenu_component.h b/src/designer/components/taskmenu/taskmenu_component.h
new file mode 100644 (file)
index 0000000..8eebb14
--- /dev/null
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/taskmenu_global.h b/src/designer/components/taskmenu/taskmenu_global.h
new file mode 100644 (file)
index 0000000..8c10de8
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/textedit_taskmenu.cpp b/src/designer/components/taskmenu/textedit_taskmenu.cpp
new file mode 100644 (file)
index 0000000..f9dfd81
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textedit_taskmenu.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_textedit_taskmenu.h>
diff --git a/src/designer/components/taskmenu/textedit_taskmenu.h b/src/designer/components/taskmenu/textedit_taskmenu.h
new file mode 100644 (file)
index 0000000..08fad6b
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/toolbar_taskmenu.cpp b/src/designer/components/taskmenu/toolbar_taskmenu.cpp
new file mode 100644 (file)
index 0000000..940ab3f
--- /dev/null
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "toolbar_taskmenu.h"
+#include "qdesigner_toolbar_p.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+
+#include <moc_toolbar_taskmenu.h>
diff --git a/src/designer/components/taskmenu/toolbar_taskmenu.h b/src/designer/components/taskmenu/toolbar_taskmenu.h
new file mode 100644 (file)
index 0000000..5e24341
--- /dev/null
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOLBAR_TASKMENU_H
+#define TOOLBAR_TASKMENU_H
+
+#include <QtDesigner/taskmenu.h>
+
+#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/components/taskmenu/treewidget_taskmenu.cpp b/src/designer/components/taskmenu/treewidget_taskmenu.cpp
new file mode 100644 (file)
index 0000000..ebcd888
--- /dev/null
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "treewidget_taskmenu.h"
+#include "treewidgeteditor.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#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
+#include <moc_treewidget_taskmenu.h>
diff --git a/src/designer/components/taskmenu/treewidget_taskmenu.h b/src/designer/components/taskmenu/treewidget_taskmenu.h
new file mode 100644 (file)
index 0000000..d8d3b33
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/treewidgeteditor.cpp b/src/designer/components/taskmenu/treewidgeteditor.cpp
new file mode 100644 (file)
index 0000000..d3caba9
--- /dev/null
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstracticoncache.h>
+#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.deleteItemButton, SIGNAL(clicked()), this, SLOT(on_deleteItemButton_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
+#include <moc_treewidgeteditor.h>
diff --git a/src/designer/components/taskmenu/treewidgeteditor.h b/src/designer/components/taskmenu/treewidgeteditor.h
new file mode 100644 (file)
index 0000000..2f06910
--- /dev/null
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/taskmenu/treewidgeteditor.ui b/src/designer/components/taskmenu/treewidgeteditor.ui
new file mode 100644 (file)
index 0000000..54b0e49
--- /dev/null
@@ -0,0 +1,257 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/widgetbox/widgetbox.cmake b/src/designer/components/widgetbox/widgetbox.cmake
new file mode 100644 (file)
index 0000000..3638cab
--- /dev/null
@@ -0,0 +1,18 @@
+set(DESIGNERCOMPONENTS_HEADERS
+    ${DESIGNERCOMPONENTS_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetboxcategorylistview.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetboxtreewidget.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox_global.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox_dnditem.h
+)
+
+set(DESIGNERCOMPONENTS_SOURCES
+    ${DESIGNERCOMPONENTS_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetboxcategorylistview.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetboxtreewidget.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox_dnditem.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/widgetbox/widgetbox.qrc
+)
+
diff --git a/src/designer/components/widgetbox/widgetbox.cpp b/src/designer/components/widgetbox/widgetbox.cpp
new file mode 100644 (file)
index 0000000..ca98cd4
--- /dev/null
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetbox.h"
+#include "widgetboxtreewidget.h"
+#include "widgetbox_dnditem.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+#include <iconloader_p.h>
+#include <qdesigner_utils_p.h>
+#include <filterwidget_p.h>
+
+#include <QtGui/qevent.h>
+#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
+
+#include <moc_widgetbox.h>
+#include <qrc_widgetbox.cpp>
diff --git a/src/designer/components/widgetbox/widgetbox.h b/src/designer/components/widgetbox/widgetbox.h
new file mode 100644 (file)
index 0000000..ccae614
--- /dev/null
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/widgetbox/widgetbox.qrc b/src/designer/components/widgetbox/widgetbox.qrc
new file mode 100644 (file)
index 0000000..7ecf78c
--- /dev/null
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/trolltech/widgetbox">
+        <file>widgetbox.xml</file>
+    </qresource>
+</RCC>
diff --git a/src/designer/components/widgetbox/widgetbox.xml b/src/designer/components/widgetbox/widgetbox.xml
new file mode 100644 (file)
index 0000000..8b71b3d
--- /dev/null
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $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/components/widgetbox/widgetbox_dnditem.cpp b/src/designer/components/widgetbox/widgetbox_dnditem.cpp
new file mode 100644 (file)
index 0000000..14ea8c2
--- /dev/null
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/abstractformeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+
+#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/components/widgetbox/widgetbox_dnditem.h b/src/designer/components/widgetbox/widgetbox_dnditem.h
new file mode 100644 (file)
index 0000000..085b48e
--- /dev/null
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/widgetbox/widgetbox_global.h b/src/designer/components/widgetbox/widgetbox_global.h
new file mode 100644 (file)
index 0000000..8780461
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/components/widgetbox/widgetboxcategorylistview.cpp b/src/designer/components/widgetbox/widgetboxcategorylistview.cpp
new file mode 100644 (file)
index 0000000..a4af694
--- /dev/null
@@ -0,0 +1,511 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxcategorylistview.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractwidgetdatabase.h>
+
+#include <QtXml/qdom.h>
+
+#include <QtGui/QIcon>
+#include <QtGui/QListView>
+#include <QtGui/QLineEdit>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QSortFilterProxyModel>
+
+#include <QtCore/qabstractitemmodel.h>
+#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
+#include <moc_widgetboxcategorylistview.h>
diff --git a/src/designer/components/widgetbox/widgetboxcategorylistview.h b/src/designer/components/widgetbox/widgetboxcategorylistview.h
new file mode 100644 (file)
index 0000000..350f545
--- /dev/null
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOXCATEGORYLISTVIEW_H
+#define WIDGETBOXCATEGORYLISTVIEW_H
+
+#include <QtDesigner/abstractwidgetbox.h>
+
+#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/components/widgetbox/widgetboxtreewidget.cpp b/src/designer/components/widgetbox/widgetboxtreewidget.cpp
new file mode 100644 (file)
index 0000000..94433d0
--- /dev/null
@@ -0,0 +1,1002 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxtreewidget.h"
+#include "widgetboxcategorylistview.h"
+
+// shared
+#include <iconloader_p.h>
+#include <sheet_delegate_p.h>
+#include <QtDesigner/abstractsettings_p.h>
+#include <ui4_p.h>
+#include <qdesigner_utils_p.h>
+#include <pluginmanager_p.h>
+
+// sdk
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractdnditem.h>
+#include <QtUiTools/customwidget.h>
+#include <QtDesigner/abstractsettings_p.h>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QApplication>
+#include <QtGui/qtreewidget.h>
+#include <QtGui/qevent.h>
+#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
+#include <moc_widgetboxtreewidget.h>
diff --git a/src/designer/components/widgetbox/widgetboxtreewidget.h b/src/designer/components/widgetbox/widgetboxtreewidget.h
new file mode 100644 (file)
index 0000000..491ceef
--- /dev/null
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $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/qxmlstream.h> // Cannot forward declare them on Mac
+#include <QtCore/qxmlstream.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerDnDItemInterface;
+
+class QTimer;
+
+namespace qdesigner_internal {
+
+class WidgetBoxCategoryListView;
+
+// WidgetBoxTreeWidget: A tree of categories
+
+class WidgetBoxTreeWidget : public QTreeWidget
+{
+    Q_OBJECT
+
+public:
+    typedef QDesignerWidgetBoxInterface::Widget Widget;
+    typedef QDesignerWidgetBoxInterface::Category Category;
+    typedef QDesignerWidgetBoxInterface::CategoryList CategoryList;
+
+    explicit WidgetBoxTreeWidget(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+    ~WidgetBoxTreeWidget();
+
+    int categoryCount() const;
+    Category category(int cat_idx) const;
+    void addCategory(const Category &cat);
+    void removeCategory(int cat_idx);
+
+    int widgetCount(int cat_idx) const;
+    Widget widget(int cat_idx, int wgt_idx) const;
+    void addWidget(int cat_idx, const Widget &wgt);
+    void removeWidget(int cat_idx, int wgt_idx);
+
+    void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
+
+    void setFileName(const QString &file_name);
+    QString fileName() const;
+    bool load(QDesignerWidgetBox::LoadMode loadMode);
+    bool loadContents(const QString &contents);
+    bool save();
+    QIcon iconForWidget(QString iconName) const;
+
+signals:
+    void pressed(const QString name, const QString dom_xml, const QPoint &global_mouse_pos);
+
+public slots:
+    void filter(const QString &);
+
+protected:
+    void contextMenuEvent(QContextMenuEvent *e);
+    void resizeEvent(QResizeEvent *e);
+
+private slots:
+    void slotSave();
+    void slotScratchPadItemDeleted();
+    void slotLastScratchPadItemDeleted();
+
+    void handleMousePress(QTreeWidgetItem *item);
+    void deleteScratchpad();
+    void slotListMode();
+    void slotIconMode();
+
+private:
+    WidgetBoxCategoryListView *addCategoryView(QTreeWidgetItem *parent, bool iconMode);
+    WidgetBoxCategoryListView *categoryViewAt(int idx) const;
+    void adjustSubListSize(QTreeWidgetItem *cat_item);
+
+    static bool readCategories(const QString &fileName, const QString &xml, CategoryList *cats, QString *errorMessage);
+    static bool readWidget(Widget *w, const QString &xml, QXmlStreamReader &r);
+
+    CategoryList loadCustomCategoryList() const;
+    void writeCategories(QXmlStreamWriter &writer, const CategoryList &cat_list) const;
+
+    int indexOfCategory(const QString &name) const;
+    int indexOfScratchpad() const;
+    int ensureScratchpad();
+    void addCustomCategories(bool replace);
+
+    void saveExpandedState() const;
+    void restoreExpandedState();
+    void updateViewMode();
+
+    QDesignerFormEditorInterface *m_core;
+    QString m_file_name;
+    typedef QHash<QString, QIcon> IconCache;
+    mutable IconCache m_pluginIcons;
+    bool m_iconMode;
+    QTimer *m_scratchPadDeleteTimer;
+};
+
+}  // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOXTREEWIDGET_H
diff --git a/src/designer/data/generate_header.xsl b/src/designer/data/generate_header.xsl
new file mode 100644 (file)
index 0000000..fa61d55
--- /dev/null
@@ -0,0 +1,465 @@
+<!DOCTYPE xsl:stylesheet [
+     <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xsl:output method="text"/>
+
+    <xsl:include href="generate_shared.xsl"/>
+
+<!-- Forward declaration -->
+
+    <xsl:template name="class-forward-declaration">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/attribute::name)"/>
+
+        <xsl:text>class </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Class declaration: child element accessors -->
+
+    <xsl:template name="child-element-accessors">
+        <xsl:param name="node"/>
+
+        <xsl:variable name="isChoice" select="name($node)='xs:choice'"/>
+
+        <xsl:if test="$isChoice">
+            <xsl:text>    enum Kind { Unknown = 0</xsl:text>
+            <xsl:for-each select="$node/xs:element">
+                <xsl:variable name="camel-case-name">
+                    <xsl:call-template name="camel-case">
+                        <xsl:with-param name="text" select="@name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+
+                <xsl:variable name="cap-name">
+                    <xsl:call-template name="cap-first-char">
+                        <xsl:with-param name="text" select="$camel-case-name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:text>, </xsl:text>
+                <xsl:value-of select="$cap-name"/>
+            </xsl:for-each>
+            <xsl:text> };&endl;</xsl:text>
+            <xsl:text>    inline Kind kind() const { return m_kind; }&endl;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="array" select="@maxOccurs='unbounded'"/>
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="return-cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-return-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="argument-cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-argument-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:text>    inline </xsl:text>
+            <xsl:value-of select="$return-cpp-type"/>
+            <xsl:text> element</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>() const { return m_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>; }&endl;</xsl:text>
+
+            <xsl:if test="$xs-type-cat = 'pointer'">
+                <xsl:text>    </xsl:text>
+                <xsl:value-of select="$return-cpp-type"/>
+                <xsl:text> takeElement</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>();&endl;</xsl:text>
+            </xsl:if>
+
+            <xsl:text>    void setElement</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>(</xsl:text>
+            <xsl:value-of select="$argument-cpp-type"/>
+            <xsl:text> a);&endl;</xsl:text>
+
+            <xsl:if test="not($isChoice) and not(@maxOccurs='unbounded')">
+                <xsl:text>    inline bool hasElement</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>() const { return m_children &amp; </xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>; }&endl;</xsl:text>
+                <xsl:text>    void clearElement</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>();&endl;</xsl:text>
+            </xsl:if>
+            <xsl:text>&endl;</xsl:text>
+
+        </xsl:for-each>
+    </xsl:template>
+
+<!-- Class declaration: child element data -->
+
+    <xsl:template name="child-element-data">
+        <xsl:param name="node"/>
+
+        <xsl:variable name="isChoice" select="$node[name()='xs:choice']"/>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-return-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="@maxOccurs='unbounded'"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:text>    </xsl:text>
+            <xsl:value-of select="$cpp-type"/>
+            <xsl:text> m_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>;&endl;</xsl:text>
+        </xsl:for-each>
+
+        <xsl:if test="not($isChoice) and not(@macOccurs='unbounded')">
+            <xsl:text>    enum Child {&endl;</xsl:text>
+            <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                    <xsl:call-template name="camel-case">
+                        <xsl:with-param name="text" select="@name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+
+                <xsl:text>        </xsl:text>
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+                <xsl:text> = </xsl:text>
+                <xsl:call-template name="powers-of-two">
+                    <xsl:with-param name="num" select="position() - 1"/>
+                </xsl:call-template>
+                <xsl:if test="position()!=last()">
+                    <xsl:text>,</xsl:text>
+                </xsl:if>
+                <xsl:text>&endl;</xsl:text>
+                                     
+            </xsl:for-each>
+            <xsl:text>    };&endl;</xsl:text>
+        </xsl:if>
+    </xsl:template>
+
+<!-- Class declaration: attribute accessors -->
+
+    <xsl:template name="attribute-accessors">
+        <xsl:param name="node"/>
+
+        <xsl:for-each select="$node/xs:attribute">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cpp-return-type">
+                <xsl:call-template name="xs-type-to-cpp-return-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cpp-argument-type">
+                <xsl:call-template name="xs-type-to-cpp-argument-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:text>    inline bool hasAttribute</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>() const { return m_has_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>; }&endl;</xsl:text>
+
+            <xsl:text>    inline </xsl:text>
+            <xsl:value-of select="$cpp-return-type"/>
+            <xsl:text> attribute</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>() const { return m_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>; }&endl;</xsl:text>
+
+            <xsl:text>    inline void setAttribute</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>(</xsl:text>
+            <xsl:value-of select="$cpp-argument-type"/>
+            <xsl:text> a) { m_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text> = a; m_has_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text> = true; }&endl;</xsl:text>
+
+            <xsl:text>    inline void clearAttribute</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>() { m_has_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text> = false; }&endl;&endl;</xsl:text>
+        </xsl:for-each>
+    </xsl:template>
+
+<!-- Class declaration -->
+
+    <xsl:template name="class-declaration">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+<!--    <xsl:variable name="hasText" select="$node[@mixed='true']"/>-->
+        <xsl:variable name="hasText" select="true()"/>
+
+        <xsl:text>class QDESIGNER_UILIB_EXPORT </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text> {&endl;</xsl:text>
+        <xsl:text>public:&endl;</xsl:text>
+        <xsl:text>    </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>();&endl;</xsl:text>
+        <xsl:text>    ~</xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>();&endl;&endl;</xsl:text>
+
+        <xsl:text>    void read(QXmlStreamReader &amp;reader);&endl;</xsl:text>
+        <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+        <xsl:text>    void read(const QDomElement &amp;node);&endl;</xsl:text>
+        <xsl:text>#endif&endl;</xsl:text>
+        <xsl:text>    void write(QXmlStreamWriter &amp;writer, const QString &amp;tagName = QString()) const;&endl;</xsl:text>
+
+        <xsl:if test="$hasText">
+            <xsl:text>    inline QString text() const { return m_text; }&endl;</xsl:text>
+            <xsl:text>    inline void setText(const QString &amp;s) { m_text = s; }&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:text>&endl;</xsl:text>
+
+        <xsl:text>    // attribute accessors&endl;</xsl:text>
+        <xsl:call-template name="attribute-accessors">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:text>    // child element accessors&endl;</xsl:text>
+
+        <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+            <xsl:call-template name="child-element-accessors">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>private:&endl;</xsl:text>
+
+        <xsl:if test="$hasText">
+            <xsl:text>    QString m_text;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:text>    void clear(bool clear_all = true);&endl;&endl;</xsl:text>
+
+        <xsl:text>    // attribute data&endl;</xsl:text>
+        <xsl:for-each select="$node/xs:attribute">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:text>    </xsl:text>
+            <xsl:value-of select="$cpp-type"/>
+            <xsl:text> m_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>;&endl;</xsl:text>
+            <xsl:text>    bool m_has_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text>;&endl;&endl;</xsl:text>
+        </xsl:for-each>
+
+        <xsl:text>    // child element data&endl;</xsl:text>
+        <xsl:if test="boolean($node/xs:choice)">
+            <xsl:text>    Kind m_kind;&endl;</xsl:text>
+        </xsl:if>
+        <xsl:if test="not($node/xs:choice)">
+            <!-- TODO: if there are no elements with maxOccurs='1', m_children is never used-->
+            <xsl:text>    uint m_children;&endl;</xsl:text>
+        </xsl:if>
+        <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+            <xsl:call-template name="child-element-data">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>&endl;</xsl:text>
+        <xsl:text>    </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>(const </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text> &amp;other);&endl;</xsl:text>
+        <xsl:text>    void operator = (const </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>&amp;other);&endl;</xsl:text>
+
+        <xsl:text>};&endl;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Root -->
+
+    <xsl:template match="xs:schema">
+
+<xsl:text>/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of Qt Designer.  This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// THIS FILE IS AUTOMATICALLY GENERATED
+
+#ifndef UI4_H
+#define UI4_H
+
+#include &lt;QtCore/QList&gt;
+#include &lt;QtCore/QString&gt;
+#include &lt;QtCore/QStringList&gt;
+#include &lt;QtCore/QXmlStreamReader&gt;
+#include &lt;QtCore/QXmlStreamWriter&gt;
+#include &lt;QtCore/qglobal.h&gt;
+
+#if defined(QT_UIC3)
+ #define QUILOADER_QDOM_READ
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QUILOADER_QDOM_READ
+ class QDomElement;
+#endif
+
+
+#define QDESIGNER_UILIB_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_UILIB_IMPORT Q_DECL_IMPORT
+
+#if defined(QT_DESIGNER_STATIC) || defined(QT_UIC) || defined(QT_UIC3)
+#  define QDESIGNER_UILIB_EXPORT
+#elif defined(QDESIGNER_UILIB_LIBRARY)
+#  define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_EXTERN
+#else
+#  define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_IMPORT
+#endif
+
+#ifndef QDESIGNER_UILIB_EXPORT
+#    define QDESIGNER_UILIB_EXPORT
+#endif
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+</xsl:text>
+
+        <xsl:text>&endl;</xsl:text>
+        <xsl:text>/*******************************************************************************&endl;</xsl:text>
+        <xsl:text>** Forward declarations&endl;</xsl:text>
+        <xsl:text>*/&endl;&endl;</xsl:text>
+
+        <xsl:for-each select="xs:complexType">
+            <xsl:call-template name="class-forward-declaration">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>&endl;</xsl:text>
+        <xsl:text>/*******************************************************************************&endl;</xsl:text>
+        <xsl:text>** Declarations&endl;</xsl:text>
+        <xsl:text>*/&endl;&endl;</xsl:text>
+
+        <xsl:for-each select="xs:complexType">
+            <xsl:call-template name="class-declaration">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+        <xsl:text>
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // UI4_H
+</xsl:text>
+    </xsl:template>
+</xsl:stylesheet>
diff --git a/src/designer/data/generate_impl.xsl b/src/designer/data/generate_impl.xsl
new file mode 100644 (file)
index 0000000..f01b4bf
--- /dev/null
@@ -0,0 +1,1161 @@
+<!DOCTYPE xsl:stylesheet [
+     <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xsl:output method="text"/>
+
+    <xsl:include href="generate_shared.xsl"/>
+
+<!-- Implementation: constructor -->
+
+    <xsl:template name="ctor-init-attributes">
+        <xsl:param name="node"/>
+        <xsl:for-each select="$node/xs:attribute">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:text>    m_has_attr_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text> = false;&endl;</xsl:text>
+            <xsl:choose>
+                <xsl:when test="@type = 'xs:integer'">
+                    <xsl:text>    m_attr_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text> = 0;&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@type = 'xs:double'">
+                    <xsl:text>    m_attr_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text> = 0.0;&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@type = 'xs:float'">
+                    <xsl:text>    m_attr_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text> = 0.0;&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@type = 'xs:boolean'">
+                    <xsl:text>    m_attr_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text> = false;&endl;</xsl:text>
+                </xsl:when>
+            </xsl:choose>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="ctor-init-child-elements">
+        <xsl:param name="node"/>
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="array" select="@maxOccurs='unbounded'"/>
+            <xsl:if test="not($array)">
+                <xsl:variable name="cpp-type">
+                    <xsl:call-template name="xs-type-to-cpp-type">
+                        <xsl:with-param name="xs-type" select="@type"/>
+                        <xsl:with-param name="array" select="$array"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:variable name="camel-case-name">
+                    <xsl:call-template name="camel-case">
+                         <xsl:with-param name="text" select="@name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:choose>
+                    <xsl:when test="@type = 'xs:integer'">
+                        <xsl:text>    m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text> = 0;&endl;</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="@type = 'xs:float'">
+                         <xsl:text>    m_</xsl:text>
+                         <xsl:value-of select="$camel-case-name"/>
+                         <xsl:text> = 0.0;&endl;</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="@type = 'xs:boolean'">
+                        <xsl:text>    m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text> = false;&endl;</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="@type = 'xs:string'"></xsl:when>
+                    <xsl:otherwise>
+                        <xsl:text>    m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text> = 0;&endl;</xsl:text>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </xsl:if>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="ctor-init-members">
+        <xsl:param name="node"/>
+
+        <xsl:if test="boolean($node/xs:choice)">
+            <xsl:text>    m_kind = Unknown;&endl;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:if test="not($node/xs:choice)">
+            <xsl:text>    m_children = 0;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:call-template name="ctor-init-attributes">
+            <xsl:with-param name="node" select="."/>
+        </xsl:call-template>
+
+        <xsl:if test="$node[@mixed='true']">
+            <xsl:text>    m_text = QLatin1String("");&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="ctor-init-child-elements">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="ctor-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:value-of select="$name"/>
+        <xsl:text>::</xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>()&endl;</xsl:text>
+        <xsl:text>{&endl;</xsl:text>
+        <xsl:call-template name="ctor-init-members">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+        <xsl:text>}&endl;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Implementation: destructor -->
+
+    <xsl:template name="dtor-delete-members">
+        <xsl:param name="node"/>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:choose>
+                <xsl:when test="@maxOccurs='unbounded'">
+                    <xsl:if test="$xs-type-cat = 'pointer'">
+                        <xsl:text>    qDeleteAll(m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text>);&endl;</xsl:text>
+                    </xsl:if>
+                    <xsl:text>    m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.clear();&endl;</xsl:text>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:if test="$xs-type-cat = 'pointer'">
+                        <xsl:text>    delete m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text>;&endl;</xsl:text>
+                    </xsl:if>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="dtor-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:value-of select="$name"/>
+        <xsl:text>::~</xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>()&endl;</xsl:text>
+        <xsl:text>{&endl;</xsl:text>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="dtor-delete-members">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>}&endl;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Implementation: clear() -->
+
+    <xsl:template name="clear-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:text>void </xsl:text><xsl:value-of select="$name"/>
+        <xsl:text>::clear(bool clear_all)&endl;</xsl:text>
+        <xsl:text>{&endl;</xsl:text>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="dtor-delete-members">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>&endl;    if (clear_all) {&endl;</xsl:text>
+
+        <xsl:choose>
+            <xsl:when test="$node[@mixed='true']">
+                <xsl:text>    m_text = QLatin1String("");&endl;</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:text>    m_text.clear();&endl;</xsl:text>
+            </xsl:otherwise>
+        </xsl:choose>
+
+        <xsl:call-template name="ctor-init-attributes">
+            <xsl:with-param name="node" select="."/>
+        </xsl:call-template>
+        <xsl:text>    }&endl;&endl;</xsl:text>
+
+        <xsl:if test="boolean($node/xs:choice)">
+            <xsl:text>    m_kind = Unknown;&endl;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:if test="not($node/xs:choice)">
+            <xsl:text>    m_children = 0;&endl;</xsl:text>
+        </xsl:if>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="ctor-init-child-elements">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>}&endl;&endl;</xsl:text>
+
+    </xsl:template>
+
+    <!-- Format a string constant as QString(QLatin1Char('X')) or QLatin1String("foo"), respectively -->
+    <xsl:template name="string-constant">
+    <xsl:param name="literal"/>
+        <xsl:choose>
+            <xsl:when test="string-length($literal) &lt; 2">
+                  <xsl:text>QString(QLatin1Char('</xsl:text>
+                <xsl:value-of select="$literal"/>
+                <xsl:text>'))</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:text>QLatin1String("</xsl:text>
+                    <xsl:value-of select="$literal"/>
+                <xsl:text>")</xsl:text>
+           </xsl:otherwise>
+       </xsl:choose>
+    </xsl:template>
+
+<!-- Implementation: read(QXmlStreamReader) -->
+
+    <xsl:template name="read-impl-load-attributes">
+        <xsl:param name="node"/>
+
+        <xsl:if test="$node/xs:attribute">
+            <xsl:text>&endl;</xsl:text>
+            <xsl:text>    foreach (const QXmlStreamAttribute &amp;attribute, reader.attributes()) {&endl;</xsl:text>
+            <xsl:text>        QStringRef name = attribute.name();&endl;</xsl:text>
+
+            <xsl:for-each select="$node/xs:attribute">
+                <xsl:variable name="camel-case-name">
+                    <xsl:call-template name="camel-case">
+                        <xsl:with-param name="text" select="@name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:variable name="cap-name">
+                    <xsl:call-template name="cap-first-char">
+                        <xsl:with-param name="text" select="$camel-case-name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:variable name="qstring-func">
+                    <xsl:call-template name="xs-type-from-qstring-func">
+                        <xsl:with-param name="xs-type" select="@type"/>
+                        <xsl:with-param name="val">
+                           <xsl:text>attribute.value().toString()</xsl:text>
+                        </xsl:with-param>
+                    </xsl:call-template>
+                </xsl:variable>
+
+                <xsl:text>        if (name == </xsl:text>
+                <xsl:call-template name="string-constant">
+                    <xsl:with-param name="literal" select="@name"/>
+                </xsl:call-template>
+                <xsl:text>) {&endl;</xsl:text>
+                <xsl:text>            setAttribute</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>(</xsl:text>
+                <xsl:value-of select="$qstring-func"/>
+                <xsl:text>);&endl;</xsl:text>
+                <xsl:text>            continue;&endl;</xsl:text>
+                <xsl:text>        }&endl;</xsl:text>
+            </xsl:for-each>
+
+            <xsl:text>        reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());&endl;</xsl:text>
+            <xsl:text>    }&endl;</xsl:text>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="read-impl-load-child-element">
+        <xsl:param name="node"/>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="lower-name">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+
+            <xsl:text>            if (tag == </xsl:text>
+            <xsl:call-template name="string-constant">
+                <xsl:with-param name="literal" select="$lower-name"/>
+            </xsl:call-template>
+            <xsl:text>) {&endl;</xsl:text>
+
+            <xsl:choose>
+                <xsl:when test="not($array) and $xs-type-cat = 'value'">
+                    <xsl:variable name="qstring-func">
+                        <xsl:call-template name="xs-type-from-qstring-func">
+                            <xsl:with-param name="xs-type" select="@type"/>
+                            <xsl:with-param name="val" select="'reader.readElementText()'"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+
+                    <xsl:text>                setElement</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>(</xsl:text>
+                    <xsl:value-of select="$qstring-func"/>
+                    <xsl:text>);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'value'">
+                    <xsl:variable name="qstring-func">
+                        <xsl:call-template name="xs-type-from-qstring-func">
+                            <xsl:with-param name="xs-type" select="@type"/>
+                            <xsl:with-param name="val" select="'reader.readElementText()'"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+
+                    <xsl:text>                m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.append(</xsl:text>
+                    <xsl:value-of select="$qstring-func"/>
+                    <xsl:text>);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="not(@maxOccurs='unbounded') and $xs-type-cat = 'pointer'">
+                    <xsl:text>                Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text> *v = new Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text>();&endl;</xsl:text>
+                    <xsl:text>                v->read(reader);&endl;</xsl:text>
+                    <xsl:text>                setElement</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>(v);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'pointer'">
+                    <xsl:text>                Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text> *v = new Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text>();&endl;</xsl:text>
+                    <xsl:text>                v->read(reader);&endl;</xsl:text>
+                    <xsl:text>                m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.append(v);&endl;</xsl:text>
+                </xsl:when>
+            </xsl:choose>
+            <xsl:text>                continue;&endl;</xsl:text>
+            <xsl:text>            }&endl;</xsl:text>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="read-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:text>void </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>::read(QXmlStreamReader &amp;reader)&endl;</xsl:text>
+
+        <xsl:text>{&endl;</xsl:text>
+
+        <xsl:call-template name="read-impl-load-attributes">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:text>&endl;</xsl:text>
+
+        <xsl:text>    for (bool finished = false; !finished &amp;&amp; !reader.hasError();) {&endl;</xsl:text>
+        <xsl:text>        switch (reader.readNext()) {&endl;</xsl:text>
+        <xsl:text>        case QXmlStreamReader::StartElement : {&endl;</xsl:text>
+        <xsl:text>            const QString tag = reader.name().toString().toLower();&endl;</xsl:text>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="read-impl-load-child-element">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>            reader.raiseError(QLatin1String("Unexpected element ") + tag);&endl;</xsl:text>
+        <xsl:text>        }&endl;</xsl:text>
+        <xsl:text>            break;&endl;</xsl:text>
+        <xsl:text>        case QXmlStreamReader::EndElement :&endl;</xsl:text>
+        <xsl:text>            finished = true;&endl;</xsl:text>
+        <xsl:text>            break;&endl;</xsl:text>
+        <xsl:text>        case QXmlStreamReader::Characters :&endl;</xsl:text>
+        <xsl:text>            if (!reader.isWhitespace())&endl;</xsl:text>
+        <xsl:text>                m_text.append(reader.text().toString());&endl;</xsl:text>
+        <xsl:text>            break;&endl;</xsl:text>
+        <xsl:text>        default :&endl;</xsl:text>
+        <xsl:text>            break;&endl;</xsl:text>
+
+        <xsl:text>        }&endl;</xsl:text>
+        <xsl:text>    }&endl;</xsl:text>
+        <xsl:text>}&endl;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Implementation: read(QDomElement) -->
+
+    <xsl:template name="read-impl-qdom-load-attributes">
+        <xsl:param name="node"/>
+
+        <xsl:if test="$node/xs:attribute">
+            <xsl:text>&endl;</xsl:text>
+
+            <xsl:for-each select="$node/xs:attribute">
+                <xsl:variable name="camel-case-name">
+                    <xsl:call-template name="camel-case">
+                        <xsl:with-param name="text" select="@name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:variable name="cap-name">
+                    <xsl:call-template name="cap-first-char">
+                        <xsl:with-param name="text" select="$camel-case-name"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:variable name="qstring-func">
+                    <xsl:call-template name="xs-type-from-qstring-func">
+                        <xsl:with-param name="xs-type" select="@type"/>
+                        <xsl:with-param name="val">
+                           <xsl:text>node.attribute(</xsl:text>
+                           <xsl:call-template name="string-constant">
+                               <xsl:with-param name="literal" select="@name"/>
+                           </xsl:call-template>
+                           <xsl:text>)</xsl:text>
+                        </xsl:with-param>
+                    </xsl:call-template>
+                </xsl:variable>
+
+                <xsl:text>    if (node.hasAttribute(</xsl:text>
+                <xsl:call-template name="string-constant">
+                    <xsl:with-param name="literal" select="@name"/>
+                </xsl:call-template>
+                <xsl:text>))&endl;</xsl:text>
+                <xsl:text>        setAttribute</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>(</xsl:text>
+                <xsl:value-of select="$qstring-func"/>
+                <xsl:text>);&endl;</xsl:text>
+            </xsl:for-each>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="read-impl-qdom-load-child-element">
+        <xsl:param name="node"/>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="lower-name">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+
+            <xsl:text>            if (tag == </xsl:text>
+            <xsl:call-template name="string-constant">
+                <xsl:with-param name="literal" select="$lower-name"/>
+            </xsl:call-template>
+            <xsl:text>) {&endl;</xsl:text>
+
+            <xsl:choose>
+                <xsl:when test="not($array) and $xs-type-cat = 'value'">
+                    <xsl:variable name="qstring-func">
+                        <xsl:call-template name="xs-type-from-qstring-func">
+                            <xsl:with-param name="xs-type" select="@type"/>
+                            <xsl:with-param name="val" select="'e.text()'"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+
+                    <xsl:text>                setElement</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>(</xsl:text>
+                    <xsl:value-of select="$qstring-func"/>
+                    <xsl:text>);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'value'">
+                    <xsl:variable name="qstring-func">
+                        <xsl:call-template name="xs-type-from-qstring-func">
+                            <xsl:with-param name="xs-type" select="@type"/>
+                            <xsl:with-param name="val" select="'e.text()'"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+
+                    <xsl:text>                m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.append(</xsl:text>
+                    <xsl:value-of select="$qstring-func"/>
+                    <xsl:text>);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="not(@maxOccurs='unbounded') and $xs-type-cat = 'pointer'">
+                    <xsl:text>                Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text> *v = new Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text>();&endl;</xsl:text>
+                    <xsl:text>                v->read(e);&endl;</xsl:text>
+                    <xsl:text>                setElement</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>(v);&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'pointer'">
+                    <xsl:text>                Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text> *v = new Dom</xsl:text>
+                    <xsl:value-of select="@type"/>
+                    <xsl:text>();&endl;</xsl:text>
+                    <xsl:text>                v->read(e);&endl;</xsl:text>
+                    <xsl:text>                m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.append(v);&endl;</xsl:text>
+                </xsl:when>
+            </xsl:choose>
+            <xsl:text>                continue;&endl;</xsl:text>
+            <xsl:text>            }&endl;</xsl:text>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="read-impl-qdom">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+
+        <xsl:text>void </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>::read(const QDomElement &amp;node)&endl;</xsl:text>
+
+        <xsl:text>{</xsl:text>
+
+        <xsl:call-template name="read-impl-qdom-load-attributes">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:text>&endl;</xsl:text>
+
+        <xsl:text>    for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {&endl;</xsl:text>
+        <xsl:text>        if (!n.isElement())&endl;</xsl:text>
+        <xsl:text>            continue;&endl;</xsl:text>
+        <xsl:text>        QDomElement e = n.toElement();&endl;</xsl:text>
+        <xsl:text>        QString tag = e.tagName().toLower();&endl;</xsl:text>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+            <xsl:call-template name="read-impl-qdom-load-child-element">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>    }&endl;</xsl:text>
+
+        <xsl:choose>
+            <xsl:when test="$node[@mixed='true']">
+                <xsl:text>    m_text = QLatin1String("");&endl;</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:text>    m_text.clear();&endl;</xsl:text>
+            </xsl:otherwise>
+        </xsl:choose>
+
+        <xsl:text>    for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {&endl;</xsl:text>
+        <xsl:text>        if (child.isText())&endl;</xsl:text>
+        <xsl:text>            m_text.append(child.nodeValue());&endl;</xsl:text>
+        <xsl:text>     }&endl;</xsl:text>
+
+        <xsl:text>}&endl;</xsl:text>
+        <xsl:text>#endif&endl;</xsl:text>
+        <xsl:text>&endl;</xsl:text>
+    </xsl:template>
+<!-- Implementation: write() -->
+
+    <xsl:template name="write-impl-save-attributes">
+        <xsl:param name="node"/>
+
+        <xsl:for-each select="$node/xs:attribute">
+        <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="lower-name">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:text>    if (hasAttribute</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>())&endl;</xsl:text>
+            <xsl:text>        writer.writeAttribute(</xsl:text>
+            <xsl:call-template name="string-constant">
+                <xsl:with-param name="literal" select="$lower-name"/>
+            </xsl:call-template>
+
+            <xsl:text>, </xsl:text>
+
+            <xsl:call-template name="xs-type-to-qstring-func">
+                <xsl:with-param name="xs-type" select="@type"/>
+                <xsl:with-param name="val" select="concat('attribute', $cap-name, '()')"/>
+            </xsl:call-template>
+
+            <xsl:text>);&endl;&endl;</xsl:text>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="write-impl-save-choice-child-element">
+        <xsl:param name="node"/>
+        <xsl:variable name="have-kind" select="name($node) = 'xs:choice'"/>
+
+        <xsl:text>    switch (kind()) {&endl;</xsl:text>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="lower-name">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:text>        case </xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>: {&endl;</xsl:text>
+                <xsl:choose>
+                    <xsl:when test="$xs-type-cat = 'value'">
+                        <xsl:variable name="qstring-func">
+                            <xsl:call-template name="xs-type-to-qstring-func">
+                                <xsl:with-param name="xs-type" select="@type"/>
+                                <xsl:with-param name="val" select="concat('element', $cap-name, '()')"/>
+                            </xsl:call-template>
+                        </xsl:variable>
+
+                        <xsl:text>            writer.writeTextElement(</xsl:text>
+                        <xsl:call-template name="string-constant">
+                            <xsl:with-param name="literal" select="$camel-case-name"/>
+                        </xsl:call-template>
+                        <xsl:text>, </xsl:text>
+                        <xsl:value-of select="$qstring-func"/>
+                        <xsl:text>);&endl;</xsl:text>
+                    </xsl:when>
+                    <xsl:when test="$xs-type-cat = 'pointer'">
+                        <xsl:variable name="cpp-return-type">
+                            <xsl:call-template name="xs-type-to-cpp-return-type">
+                                <xsl:with-param name="xs-type" select="@type"/>
+                            </xsl:call-template>
+                        </xsl:variable>
+
+                        <xsl:text>            </xsl:text>
+                        <xsl:value-of select="$cpp-return-type"/>
+                        <xsl:text> v = element</xsl:text>
+                        <xsl:value-of select="$cap-name"/>
+                        <xsl:text>();&endl;</xsl:text>
+                        <xsl:text>            if (v != 0) {&endl;</xsl:text>
+                        <xsl:text>                v->write(writer, </xsl:text>
+                        <xsl:call-template name="string-constant">
+                            <xsl:with-param name="literal" select="$lower-name"/>
+                        </xsl:call-template>
+                        <xsl:text>);&endl;</xsl:text>
+                        <xsl:text>            }&endl;</xsl:text>
+                    </xsl:when>
+                </xsl:choose>
+            <xsl:text>            break;&endl;</xsl:text>
+            <xsl:text>        }&endl;</xsl:text>
+        </xsl:for-each>
+
+        <xsl:text>        default:&endl;</xsl:text>
+        <xsl:text>            break;&endl;</xsl:text>
+        <xsl:text>    }&endl;</xsl:text>
+    </xsl:template>
+
+    <xsl:template name="write-impl-save-sequence-child-element">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="lower-name">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cpp-return-type">
+                <xsl:call-template name="xs-type-to-cpp-return-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:choose>
+                <xsl:when test="@maxOccurs='unbounded'">
+                    <xsl:text>    for (int i = 0; i &lt; m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>.size(); ++i) {&endl;</xsl:text>
+                    <xsl:text>        </xsl:text>
+                    <xsl:value-of select="$cpp-return-type"/>
+                    <xsl:text> v = m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>[i];&endl;</xsl:text>
+                    <xsl:choose>
+                        <xsl:when test="$xs-type-cat = 'pointer'">
+                            <xsl:text>        v->write(writer, </xsl:text>
+                            <xsl:call-template name="string-constant">
+                                <xsl:with-param name="literal" select="$lower-name"/>
+                            </xsl:call-template>
+                            <xsl:text>);&endl;</xsl:text>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:variable name="qstring-func">
+                                <xsl:call-template name="xs-type-to-qstring-func">
+                                    <xsl:with-param name="xs-type" select="@type"/>
+                                    <xsl:with-param name="val" select="'v'"/>
+                                </xsl:call-template>
+                            </xsl:variable>
+
+                            <xsl:text>        writer.writeTextElement(</xsl:text>
+                            <xsl:call-template name="string-constant">
+                                <xsl:with-param name="literal" select="$lower-name"/>
+                            </xsl:call-template>
+                            <xsl:text>, </xsl:text>
+                            <xsl:value-of select="$qstring-func"/>
+                            <xsl:text>);&endl;</xsl:text>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                    <xsl:text>    }&endl;</xsl:text>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:text>    if (m_children &amp; </xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>) {&endl;</xsl:text>
+                    <xsl:choose>
+                        <xsl:when test="$xs-type-cat = 'pointer'">
+                            <xsl:text>        m_</xsl:text>
+                            <xsl:value-of select="$camel-case-name"/>
+                            <xsl:text>->write(writer, </xsl:text>
+                            <xsl:call-template name="string-constant">
+                                <xsl:with-param name="literal" select="$lower-name"/>
+                            </xsl:call-template>
+                            <xsl:text>);&endl;</xsl:text>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:variable name="qstring-func">
+                                <xsl:call-template name="xs-type-to-qstring-func">
+                                    <xsl:with-param name="xs-type" select="@type"/>
+                                    <xsl:with-param name="val" select="concat('m_', $camel-case-name)"/>
+                                </xsl:call-template>
+                            </xsl:variable>
+                            <xsl:text>        writer.writeTextElement(</xsl:text>
+                            <xsl:call-template name="string-constant">
+                                <xsl:with-param name="literal" select="$lower-name"/>
+                            </xsl:call-template>
+                            <xsl:text>, </xsl:text>
+                            <xsl:value-of select="$qstring-func"/>
+                            <xsl:text>);&endl;</xsl:text>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                    <xsl:text>    }&endl;&endl;</xsl:text>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="write-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+        <xsl:variable name="lower-name">
+            <xsl:call-template name="lower-text">
+                <xsl:with-param name="text" select="@name"/>
+            </xsl:call-template>
+        </xsl:variable>
+
+        <xsl:text>void </xsl:text>
+        <xsl:value-of select="$name"/>
+        <xsl:text>::write(QXmlStreamWriter &amp;writer, const QString &amp;tagName) const&endl;</xsl:text>
+        <xsl:text>{&endl;</xsl:text>
+
+        <xsl:text>    writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("</xsl:text>
+        <xsl:value-of select="$lower-name"/>
+        <xsl:text>") : tagName.toLower());&endl;&endl;</xsl:text>
+
+        <xsl:call-template name="write-impl-save-attributes">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:for-each select="$node//xs:choice">
+            <xsl:call-template name="write-impl-save-choice-child-element">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:for-each select="$node//xs:sequence | $node//xs:all">
+            <xsl:call-template name="write-impl-save-sequence-child-element">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+
+        <xsl:text>    if (!m_text.isEmpty())&endl;</xsl:text>
+        <xsl:text>        writer.writeCharacters(m_text);&endl;&endl;</xsl:text>
+
+        <xsl:text>    writer.writeEndElement();&endl;</xsl:text>
+        <xsl:text>}&endl;&endl;</xsl:text>
+    </xsl:template>
+
+<!-- Implementation: child element setters -->
+
+    <xsl:template name="child-setter-impl-helper">
+        <xsl:param name="node"/>
+        <xsl:param name="name"/>
+        <xsl:variable name="make-kind-enum" select="name($node)='xs:choice'"/>
+        <xsl:variable name="isChoice" select="name($node)='xs:choice'"/>
+
+        <xsl:for-each select="$node/xs:element">
+            <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+            <xsl:variable name="camel-case-name">
+                <xsl:call-template name="camel-case">
+                    <xsl:with-param name="text" select="@name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="cap-name">
+                <xsl:call-template name="cap-first-char">
+                    <xsl:with-param name="text" select="$camel-case-name"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="return-cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-return-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="argument-cpp-type">
+                <xsl:call-template name="xs-type-to-cpp-argument-type">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="xs-type-cat">
+                <xsl:call-template name="xs-type-category">
+                    <xsl:with-param name="xs-type" select="@type"/>
+                    <xsl:with-param name="array" select="$array"/>
+                </xsl:call-template>
+            </xsl:variable>
+
+            <xsl:if test="$xs-type-cat = 'pointer'">
+                <xsl:value-of select="$return-cpp-type"/>
+                <xsl:text> </xsl:text>
+                <xsl:value-of select="$name"/>
+                <xsl:text>::takeElement</xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>() &endl;{&endl;</xsl:text>
+                <xsl:text>    </xsl:text>
+                <xsl:value-of select="$return-cpp-type"/>
+                <xsl:text> a = m_</xsl:text>
+                <xsl:value-of select="$camel-case-name"/>
+                <xsl:text>;&endl;</xsl:text>
+                <xsl:text>    m_</xsl:text>
+                <xsl:value-of select="$camel-case-name"/>
+                <xsl:text> = 0;&endl;</xsl:text>
+                <xsl:if test="not($isChoice)">
+                    <xsl:text>    m_children ^= </xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>;&endl;</xsl:text>
+                </xsl:if>
+                <xsl:text>    return a;&endl;</xsl:text>
+                <xsl:text>}&endl;&endl;</xsl:text>
+            </xsl:if>
+
+            <xsl:text>void </xsl:text>
+            <xsl:value-of select="$name"/>
+            <xsl:text>::setElement</xsl:text>
+            <xsl:value-of select="$cap-name"/>
+            <xsl:text>(</xsl:text>
+            <xsl:value-of select="$argument-cpp-type"/>
+            <xsl:text> a)&endl;</xsl:text>
+            <xsl:text>{&endl;</xsl:text>
+            <xsl:choose>
+                <xsl:when test="$make-kind-enum">
+                    <xsl:text>    clear(false);&endl;</xsl:text>
+                    <xsl:text>    m_kind = </xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>;&endl;</xsl:text>
+                </xsl:when>
+                <xsl:when test="$xs-type-cat = 'pointer'">
+                    <xsl:text>    delete </xsl:text>
+                    <xsl:text>m_</xsl:text>
+                    <xsl:value-of select="$camel-case-name"/>
+                    <xsl:text>;&endl;</xsl:text>
+                </xsl:when>
+            </xsl:choose>
+            <xsl:if test="not($isChoice)">
+                <xsl:text>    m_children |= </xsl:text>
+                <xsl:value-of select="$cap-name"/>
+                <xsl:text>;&endl;</xsl:text>
+            </xsl:if>
+            <xsl:text>    m_</xsl:text>
+            <xsl:value-of select="$camel-case-name"/>
+            <xsl:text> = a;&endl;</xsl:text>
+            <xsl:text>}&endl;&endl;</xsl:text>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="child-setter-impl">
+        <xsl:param name="node"/>
+        <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+        <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+            <xsl:call-template name="child-setter-impl-helper">
+                <xsl:with-param name="node" select="."/>
+                <xsl:with-param name="name" select="$name"/>
+            </xsl:call-template>
+        </xsl:for-each>
+    </xsl:template>
+
+    <xsl:template name="child-clear-impl">
+        <xsl:param name="node"/>
+
+       <xsl:variable name="name" select="concat('Dom', @name)"/>
+       <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+            <xsl:variable name="isChoice" select="name()='xs:choice'"/>
+            <xsl:variable name="make-child-enum" select="boolean(xs:sequence) and not(@maxOccurs='unbounded')"/>
+
+            <xsl:for-each select="xs:element">
+                <xsl:if test="not($isChoice) and not(@maxOccurs='unbounded')">
+                    <xsl:variable name="camel-case-name">
+                        <xsl:call-template name="camel-case">
+                            <xsl:with-param name="text" select="@name"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+                    <xsl:variable name="cap-name">
+                        <xsl:call-template name="cap-first-char">
+                            <xsl:with-param name="text" select="$camel-case-name"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+                    <xsl:variable name="xs-type-cat">
+                        <xsl:call-template name="xs-type-category">
+                            <xsl:with-param name="xs-type" select="@type"/>
+                            <xsl:with-param name="array" select="@maxOccurs='unbounded'"/>
+                        </xsl:call-template>
+                    </xsl:variable>
+
+                    <xsl:text>void </xsl:text>
+                    <xsl:value-of select="$name"/>
+                    <xsl:text>::clearElement</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>()&endl;</xsl:text>
+                    <xsl:text>{&endl;</xsl:text>
+                    <xsl:if test="$xs-type-cat = 'pointer'">
+                        <xsl:text>    delete m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text>;&endl;</xsl:text>
+                        <xsl:text>    m_</xsl:text>
+                        <xsl:value-of select="$camel-case-name"/>
+                        <xsl:text> = 0;&endl;</xsl:text>
+                    </xsl:if>
+                    <xsl:text>    m_children &amp;= ~</xsl:text>
+                    <xsl:value-of select="$cap-name"/>
+                    <xsl:text>;&endl;</xsl:text>
+                    <xsl:text>}&endl;&endl;</xsl:text>
+                </xsl:if>
+            </xsl:for-each>
+        </xsl:for-each>
+    </xsl:template>
+
+
+<!-- Implementation -->
+
+    <xsl:template name="class-implementation">
+        <xsl:param name="node"/>
+
+        <xsl:call-template name="clear-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="ctor-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="dtor-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="read-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="read-impl-qdom">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="write-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="child-setter-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+        <xsl:call-template name="child-clear-impl">
+            <xsl:with-param name="node" select="$node"/>
+        </xsl:call-template>
+
+    </xsl:template>
+
+<!-- Root -->
+
+    <xsl:template match="xs:schema">
+
+<xsl:text>/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+</xsl:text>
+        <xsl:text>#include "ui4_p.h"&endl;</xsl:text>
+        <xsl:text>&endl;</xsl:text>
+        <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+        <xsl:text>#include &lt;QtXml/QDomElement&gt;&endl;</xsl:text>
+        <xsl:text>#endif&endl;</xsl:text>
+        <xsl:text>&endl;</xsl:text>
+        <xsl:text>QT_BEGIN_NAMESPACE&endl;</xsl:text>
+
+        <xsl:text>#ifdef QFORMINTERNAL_NAMESPACE&endl;</xsl:text>
+        <xsl:text>using namespace QFormInternal;&endl;</xsl:text>
+        <xsl:text>#endif&endl;</xsl:text>
+        <xsl:text>&endl;</xsl:text>
+
+        <xsl:text>/*******************************************************************************&endl;</xsl:text>
+        <xsl:text>** Implementations&endl;</xsl:text>
+        <xsl:text>*/&endl;&endl;</xsl:text>
+
+        <xsl:for-each select="xs:complexType">
+            <xsl:call-template name="class-implementation">
+                <xsl:with-param name="node" select="."/>
+            </xsl:call-template>
+        </xsl:for-each>
+        <xsl:text>QT_END_NAMESPACE&endl;</xsl:text>
+
+        <xsl:text>&endl;</xsl:text>
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/designer/data/generate_shared.xsl b/src/designer/data/generate_shared.xsl
new file mode 100644 (file)
index 0000000..ec95fe2
--- /dev/null
@@ -0,0 +1,331 @@
+<!DOCTYPE xsl:stylesheet [
+     <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<!-- Hack to make names camel case
+     All names in UI files are lowercase, while the element names are
+     capital case. To make the UI files conforming to the XSD file + keep
+     the DOM interface we rename them here -->
+    <xsl:template name="camel-case">
+        <xsl:param name="text"/>
+    <xsl:choose>
+        <xsl:when test="$text='exportmacro'">exportMacro</xsl:when>
+        <xsl:when test="$text='layoutdefault'">layoutDefault</xsl:when>
+        <xsl:when test="$text='layoutfunction'">layoutFunction</xsl:when>
+        <xsl:when test="$text='pixmapfunction'">pixmapFunction</xsl:when>
+        <xsl:when test="$text='customwidgets'">customWidgets</xsl:when>
+        <xsl:when test="$text='tabstops'">tabStops</xsl:when>
+        <xsl:when test="$text='tabstop'">tabStop</xsl:when>
+        <xsl:when test="$text='buttongroups'">buttonGroups</xsl:when>
+        <xsl:when test="$text='exportmacro'">exportMacro</xsl:when>
+        <xsl:when test="$text='actiongroup'">actionGroup</xsl:when>
+        <xsl:when test="$text='buttongroup'">buttonGroup</xsl:when>
+        <xsl:when test="$text='customwidget'">customWidget</xsl:when>
+        <xsl:when test="$text='sizehint'">sizeHint</xsl:when>
+        <xsl:when test="$text='addpagemethod'">addPageMethod</xsl:when>
+        <xsl:when test="$text='sizepolicy'">sizePolicy</xsl:when>
+        <xsl:when test="$text='hordata'">horData</xsl:when>
+        <xsl:when test="$text='verdata'">verData</xsl:when>
+        <xsl:when test="$text='rowspan'">rowSpan</xsl:when>
+        <xsl:when test="$text='colspan'">colSpan</xsl:when>
+        <xsl:when test="$text='addaction'">addAction</xsl:when>
+        <xsl:when test="$text='zorder'">zOrder</xsl:when>
+        <xsl:when test="$text='startx'">startX</xsl:when>
+        <xsl:when test="$text='starty'">startY</xsl:when>
+        <xsl:when test="$text='endx'">endX</xsl:when>
+        <xsl:when test="$text='endy'">endY</xsl:when>
+        <xsl:when test="$text='centralx'">centralX</xsl:when>
+        <xsl:when test="$text='centraly'">centralY</xsl:when>
+        <xsl:when test="$text='focalx'">focalX</xsl:when>
+        <xsl:when test="$text='focaly'">focalY</xsl:when>
+        <xsl:when test="$text='widgetdata'">widgetData</xsl:when>
+        <xsl:when test="$text='coordinatemode'">coordinateMode</xsl:when>
+        <xsl:when test="$text='brushstyle'">brushStyle</xsl:when>
+        <xsl:when test="$text='colorrole'">colorRole</xsl:when>
+        <xsl:when test="$text='pointsize'">pointSize</xsl:when>
+        <xsl:when test="$text='strikeout'">strikeOut</xsl:when>
+        <xsl:when test="$text='stylestrategy'">styleStrategy</xsl:when>
+        <xsl:when test="$text='hsizetype'">hSizeType</xsl:when>
+        <xsl:when test="$text='vsizetype'">vSizeType</xsl:when>
+        <xsl:when test="$text='horstretch'">horStretch</xsl:when>
+        <xsl:when test="$text='verstretch'">verStretch</xsl:when>
+        <xsl:when test="$text='normaloff'">normalOff</xsl:when>
+        <xsl:when test="$text='normalon'">normalOn</xsl:when>
+        <xsl:when test="$text='disabledoff'">disabledOff</xsl:when>
+        <xsl:when test="$text='disabledon'">disabledOn</xsl:when>
+        <xsl:when test="$text='activeoff'">activeOff</xsl:when>
+        <xsl:when test="$text='activeon'">activeOn</xsl:when>
+        <xsl:when test="$text='selectedoff'">selectedOff</xsl:when>
+        <xsl:when test="$text='selectedon'">selectedOn</xsl:when>
+        <xsl:when test="$text='cursorshape'">cursorShape</xsl:when>
+        <xsl:when test="$text='iconset'">iconSet</xsl:when>
+        <xsl:when test="$text='stringlist'">stringList</xsl:when>
+        <xsl:when test="$text='datetime'">dateTime</xsl:when>
+        <xsl:when test="$text='pointf'">pointF</xsl:when>
+        <xsl:when test="$text='rectf'">rectF</xsl:when>
+        <xsl:when test="$text='sizef'">sizeF</xsl:when>
+        <xsl:when test="$text='longlong'">longLong</xsl:when>
+        <xsl:when test="$text='uint'">UInt</xsl:when>
+        <xsl:when test="$text='ulonglong'">uLongLong</xsl:when>
+        <xsl:when test="$text='rowstretch'">rowStretch</xsl:when>
+        <xsl:when test="$text='columnstretch'">columnStretch</xsl:when>
+        <xsl:when test="$text='rowminimumheight'">rowMinimumHeight</xsl:when>
+        <xsl:when test="$text='columnminimumwidth'">columnMinimumWidth</xsl:when>
+        <xsl:when test="$text='extracomment'">extraComment</xsl:when>
+       <xsl:otherwise><xsl:value-of select="$text"/></xsl:otherwise>
+    </xsl:choose>
+    </xsl:template>
+
+
+<!-- Convenience templates -->
+
+    <xsl:template name="cap-first-char">
+        <xsl:param name="text"/>
+        <xsl:value-of select="concat(translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($text, 2))" />
+    </xsl:template>
+
+    <xsl:template name="lower-text">
+        <xsl:param name="text"/>
+
+        <xsl:if test="boolean($text)">
+            <xsl:variable name="head" select="substring($text, 1, 1)"/>
+            <xsl:variable name="tail" select="substring($text, 2)"/>
+            <xsl:variable name="lower-head" select="translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
+            <xsl:variable name="lower-tail">
+                <xsl:call-template name="lower-text">
+                    <xsl:with-param name="text" select="tail"/>
+                </xsl:call-template>
+            </xsl:variable>
+            <xsl:value-of select='concat($lower-head, $lower-tail)'/>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="powers-of-two">
+        <xsl:param name="num"/>
+
+        <xsl:choose>
+            <xsl:when test="$num=0">1</xsl:when>
+            <xsl:otherwise>
+                <xsl:variable name="x">
+                    <xsl:call-template name="powers-of-two">
+                        <xsl:with-param name="num" select="$num - 1"/>
+                    </xsl:call-template>
+                </xsl:variable>
+                <xsl:value-of select="2*$x"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+<!-- Convenience templates: xs-types to c++ types conversions -->
+
+    <xsl:template name="xs-type-from-qstring-func">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="val"/>
+        <xsl:choose>
+            <xsl:when test="$xs-type='xs:string'">
+                <xsl:value-of select="$val"/>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:integer'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toInt()</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:float'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toFloat()</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:double'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toDouble()</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:boolean'">
+                <xsl:text>(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text> == QLatin1String("true") ? true : false)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:long'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toLongLong()</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:unsignedInt'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toUInt()</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:unsignedLong'">
+                <xsl:value-of select="$val"/>
+                <xsl:text>.toULongLong()</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>### BZZZZT! ###</xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="xs-type-to-qstring-func">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="val"/>
+        <xsl:choose>
+            <xsl:when test="$xs-type='xs:string'">
+                <xsl:value-of select="$val"/>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:integer'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:long'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:unsignedInt'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:unsignedLong'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:float'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>, 'f', 8)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:double'">
+                <xsl:text>QString::number(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text>, 'f', 15)</xsl:text>
+            </xsl:when>
+            <xsl:when test="$xs-type='xs:boolean'">
+                <xsl:text>(</xsl:text>
+                <xsl:value-of select="$val"/>
+                <xsl:text> ? QLatin1String("true") : QLatin1String("false"))</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>### BZZZZT! ###</xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="xs-type-category">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="array" select="false"/>
+        <xsl:choose>
+            <xsl:when test="$array">value</xsl:when>
+            <xsl:otherwise>
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">value</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">value</xsl:when>
+                    <xsl:otherwise>pointer</xsl:otherwise>
+                </xsl:choose>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="xs-type-to-cpp-type">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="array" select="false"/>
+        <xsl:choose>
+            <xsl:when test="$array">
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">QStringList</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">QList&lt;int&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">QList&lt;float&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">QList&lt;double&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">QList&lt;bool&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">QList&lt;qlonglong&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">QList&lt;uint&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">QList&lt;qulonglong&gt;</xsl:when>
+                    <xsl:otherwise>QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;</xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">QString</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+                    <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/></xsl:otherwise>
+                </xsl:choose>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="xs-type-to-cpp-return-type">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="array" select="false"/>
+        <xsl:choose>
+            <xsl:when test="$array">
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">QStringList</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">QList&lt;int&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">QList&lt;float&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">QList&lt;double&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">QList&lt;bool&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">QList&lt;qlonglong&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">QList&lt;uint&gt;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">QList&lt;qulonglong&gt;</xsl:when>
+                    <xsl:otherwise>QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;</xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">QString</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+                    <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/>*</xsl:otherwise>
+                </xsl:choose>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="xs-type-to-cpp-argument-type">
+        <xsl:param name="xs-type"/>
+        <xsl:param name="array" select="false"/>
+        <xsl:choose>
+            <xsl:when test="$array">
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">const QStringList&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">const QList&lt;int&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">const QList&lt;float&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">const QList&lt;double&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">const QList&lt;bool&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">const QList&lt;qlonglong&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">const QList&lt;uint&gt;&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">const QList&lt;qulonglong&gt;&amp;</xsl:when>
+                    <xsl:otherwise>const QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;&amp;</xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:choose>
+                    <xsl:when test="$xs-type='xs:string'">const QString&amp;</xsl:when>
+                    <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+                    <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+                    <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+                    <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+                    <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+                    <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+                    <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/>*</xsl:otherwise>
+                </xsl:choose>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/src/designer/data/ui3.xsd b/src/designer/data/ui3.xsd
new file mode 100644 (file)
index 0000000..06f325e
--- /dev/null
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+       
+       <xs:element name="UI">
+               <xs:complexType>
+                       <xs:choice maxOccurs="unbounded">
+                               <xs:element name="actions">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="action">
+                                                               <xs:complexType>
+                                                                       <xs:sequence maxOccurs="unbounded">
+                                                                               <xs:element name="property" type="property" />
+                                                                       </xs:sequence>
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="author" type="xs:string" />
+                               <xs:element name="class" type="xs:string" />
+                               <xs:element name="comment" type="xs:string" />
+                               <xs:element name="connections">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="connection">
+                                                               <xs:complexType>
+                                                                       <xs:sequence>
+                                                                               <xs:element name="sender" type="xs:string" />
+                                                                               <xs:element name="signal" type="xs:string" />
+                                                                               <xs:element name="receiver" type="xs:string" />
+                                                                               <xs:element name="slot" type="xs:string" />
+                                                                       </xs:sequence>
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="customWidgets" type="xs:string" />
+                               <xs:element name="exportmacro" type="xs:string" />
+                               <xs:element name="forwards">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="forward" type="xs:string" />
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="images">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="image">
+                                                               <xs:complexType>
+                                                                       <xs:sequence>
+                                                                               <xs:element name="data">
+                                                                                       <xs:complexType>
+                                                                                               <xs:sequence />
+                                                                                               <xs:attribute name="format" type="xs:string" />
+                                                                                               <xs:attribute name="length" type="xs:integer" />
+                                                                                       </xs:complexType>
+                                                                               </xs:element>
+                                                                       </xs:sequence>
+                                                                       <xs:attribute name="name" type="xs:string" />
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="includes">
+                                       <xs:complexType>                                                
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="include">
+                                                               <xs:complexType>
+                                                                       <xs:simpleContent>
+                                                                               <xs:extension base="xs:string">
+                                                                                       <xs:attribute name="location" type="xs:string" />
+                                                                                       <xs:attribute name="impldecl" type="xs:string" />
+                                                                               </xs:extension>
+                                                                       </xs:simpleContent>
+                                                               </xs:complexType>
+                                                       </xs:element>                                                                   
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="layoutDefaults">
+                                       <xs:complexType>
+                                               <xs:sequence />
+                                               <xs:attribute name="spacing" type="xs:integer" />
+                                               <xs:attribute name="margin" type="xs:integer" />
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="layoutFunctions">
+                                       <xs:complexType>
+                                               <xs:sequence />
+                                               <xs:attribute name="spacing" type="xs:string" />
+                                               <xs:attribute name="margin" type="xs:string" />
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="menubar">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                                       <xs:choice maxOccurs="unbounded">
+                                                               <xs:element name="property" type="property" />
+                                                               <xs:element name="item">
+                                                                       <xs:complexType>
+                                                                               <xs:sequence>
+                                                                                       <xs:choice maxOccurs="unbounded">
+                                                                                               <xs:element name="action">
+                                                                                                       <xs:complexType>
+                                                                                                               <xs:sequence />
+                                                                                                               <xs:attribute name="name" type="xs:string" />
+                                                                                                       </xs:complexType>
+                                                                                               </xs:element>
+                                                                                               <xs:element name="item">
+                                                                                               </xs:element>
+                                                                                               <xs:element name="separator" type="xs:string" />
+                                                                                       </xs:choice>
+                                                                               </xs:sequence>
+                                                                               <xs:attribute name="name" type="xs:string" />
+                                                                               <xs:attribute name="text" type="xs:string" />
+                                                                       </xs:complexType>
+                                                               </xs:element>
+                                                       </xs:choice>
+                                                       <xs:element name="class" type="xs:string" />
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="pixmapfunction" type="xs:string" />
+                               <xs:element name="signals">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="signal" type="xs:string" />
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="slots">
+                                       <xs:complexType>                                                
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="slot">
+                                                               <xs:complexType>
+                                                                       <xs:simpleContent>
+                                                                               <xs:extension base="xs:string">
+                                                                                       <xs:attribute name="access" type="xs:string" />
+                                                                                       <xs:attribute name="specifier" type="xs:string" />
+                                                                                       <xs:attribute name="language" type="xs:string" />
+                                                                                       <xs:attribute name="returnType" type="xs:string" />
+                                                                               </xs:extension>
+                                                                       </xs:simpleContent>
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="tabstops">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="tabstop" type="xs:string" />
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="toolbars">
+                                       <xs:complexType>
+                                               <xs:sequence maxOccurs="unbounded">
+                                                       <xs:element name="toolbar">
+                                                               <xs:complexType>
+                                                                       <xs:choice maxOccurs="unbounded">
+                                                                               <xs:element name="property" type="property" />
+                                                                               <xs:element name="action">
+                                                                                       <xs:complexType>
+                                                                                               <xs:sequence />
+                                                                                               <xs:attribute name="name" type="xs:string" />
+                                                                                       </xs:complexType>
+                                                                               </xs:element>
+                                                                               <xs:element name="separator" type="xs:string" />
+                                                                       </xs:choice>
+                                                                       <xs:attribute name="dock" type="xs:integer" />
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="variables">
+                                       <xs:complexType>
+                                               <xs:sequence>
+                                                       <xs:element name="variable">
+                                                               <xs:complexType>
+                                                                       <xs:sequence />
+                                                                       <xs:attribute name="access" type="xs:string" />
+                                                               </xs:complexType>
+                                                       </xs:element>
+                                               </xs:sequence>
+                                       </xs:complexType>
+                               </xs:element>
+                               <xs:element name="widget" type="widget" />
+                               <xs:element name="include" type="xs:string" />
+                               <xs:element name="variable" type="xs:string" />
+                       </xs:choice>
+                       <xs:attribute name="version" type="xs:string" />
+                       <xs:attribute name="stdsetdef" type="xs:integer" />
+               </xs:complexType>
+       </xs:element>
+
+       <xs:complexType name="layout">
+               <xs:choice maxOccurs="unbounded">
+                       <xs:element name="property" type="property" />
+                       <xs:element name="widget" type="widget" />
+                       <xs:element name="spacer" type="spacer" />
+               </xs:choice>
+       </xs:complexType>
+       
+       <xs:complexType name="widget">
+                       <xs:choice maxOccurs="unbounded">
+                               <xs:element name="class" type="xs:string" />
+                               <xs:element name="property" type="property" />
+                               <xs:element name="hbox" type="layout" />
+                               <xs:element name="vbox" type="layout" />
+                               <xs:element name="grid" type="layout" />
+                               <xs:element name="widget" type="widget" />
+                       </xs:choice>
+               <xs:attribute name="class" type="xs:string" />
+               <xs:attribute name="row" type="xs:integer" />            <!-- ### remove me -->
+               <xs:attribute name="column" type="xs:integer" />         <!-- ### remove me -->
+       </xs:complexType>
+               
+       <xs:complexType name="spacer">
+               <xs:sequence maxOccurs="unbounded">
+                       <xs:element name="property" type="property" />
+               </xs:sequence>
+               <xs:attribute name="row" type="xs:integer" />            <!-- ### remove me -->
+               <xs:attribute name="column" type="xs:integer" />         <!-- ### remove me -->
+               <xs:attribute name="rowspan" type="xs:integer" />        <!-- ### remove me -->
+               <xs:attribute name="colspan" type="xs:integer" />        <!-- ### remove me -->
+       </xs:complexType>
+
+       <xs:complexType name="color">
+               <xs:sequence>
+                       <xs:element name="red" type="xs:integer" />
+                       <xs:element name="green" type="xs:integer" />
+                       <xs:element name="blue" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+       
+       <xs:complexType name="colorGroup">
+               <xs:choice maxOccurs="unbounded">
+                       <xs:element name="color" type="color" />
+                       <xs:element name="pixmap" type="xs:string" />
+               </xs:choice>
+       </xs:complexType>
+
+       <xs:complexType name="palette">
+               <xs:sequence>
+                       <xs:element name="active" type="colorGroup" />
+                       <xs:element name="inactive" type="colorGroup" />
+                       <xs:element name="disabled" type="colorGroup" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="font">
+               <xs:sequence>
+                       <xs:element name="family" type="xs:string" />
+                       <xs:element name="pointSize" type="xs:integer" />
+                       <xs:element name="weight" type="xs:integer" />
+                       <xs:element name="italic" type="xs:boolean" />
+                       <xs:element name="bold" type="xs:boolean" />
+                       <xs:element name="underline" type="xs:boolean" />
+                       <xs:element name="strikeout" type="xs:boolean" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="point">
+               <xs:sequence>
+                       <xs:element name="x" type="xs:integer" />
+                       <xs:element name="y" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+       
+       <xs:complexType name="rect">
+               <xs:sequence>
+                       <xs:element name="x" type="xs:integer" />
+                       <xs:element name="y" type="xs:integer" />
+                       <xs:element name="width" type="xs:integer" />
+                       <xs:element name="height" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="sizePolicy">
+               <xs:sequence>
+                       <xs:element name="hsizetype" type="xs:integer" />
+                       <xs:element name="vsizetype" type="xs:integer" />
+                       <xs:element name="horstretch" type="xs:integer" />
+                       <xs:element name="verstretch" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="size">
+               <xs:sequence>
+                       <xs:element name="width" type="xs:integer" />
+                       <xs:element name="height" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+       
+       <xs:complexType name="date">
+               <xs:sequence>
+                       <xs:element name="year" type="xs:integer" />
+                       <xs:element name="month" type="xs:integer" />
+                       <xs:element name="day" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="time">
+               <xs:sequence>
+                       <xs:element name="hour" type="xs:integer" />
+                       <xs:element name="minute" type="xs:integer" />
+                       <xs:element name="second" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+       
+       <xs:complexType name="dateTime">
+               <xs:sequence>
+                       <xs:element name="hour" type="xs:integer" />
+                       <xs:element name="minute" type="xs:integer" />
+                       <xs:element name="second" type="xs:integer" />
+                       <xs:element name="year" type="xs:integer" />
+                       <xs:element name="month" type="xs:integer" />
+                       <xs:element name="day" type="xs:integer" />
+               </xs:sequence>
+       </xs:complexType>
+
+       <xs:complexType name="property">
+               <xs:choice>
+                       <xs:element name="bool" type="xs:boolean" />
+                       <xs:element name="color" type="color" />
+                       <xs:element name="cstring" type="xs:string" />
+                       <xs:element name="cursor" type="xs:integer" />
+                       <xs:element name="enum" type="xs:string" />
+                       <xs:element name="font" type ="font" />
+                       <xs:element name="iconset" type="xs:string" />
+                       <xs:element name="palette" type="palette" />
+                       <xs:element name="point" type="point" />
+                       <xs:element name="rect" type="rect" />
+                       <xs:element name="set" type="xs:string" />
+                       <xs:element name="sizePolicy" type="sizePolicy" />
+                       <xs:element name="size" type="size" />
+                       <xs:element name="string" type="xs:string" />
+                       <xs:element name="number" type="xs:integer" />
+                       <xs:element name="date" type="date" />
+                       <xs:element name="time" type="time" />
+                       <xs:element name="dateTime" type="dateTime" />
+               </xs:choice>
+               <xs:attribute name="name" type="xs:string" />
+               <xs:attribute name="stdset" type="xs:integer" />
+       </xs:complexType>
+       
+</xs:schema>
\ No newline at end of file
diff --git a/src/designer/data/ui4.xsd b/src/designer/data/ui4.xsd
new file mode 100644 (file)
index 0000000..53bae62
--- /dev/null
@@ -0,0 +1,589 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+        <xs:element name="ui" type="UI"/>
+
+        <xs:complexType name="UI">
+                <xs:all>
+                        <xs:element name="author" type="xs:string" minOccurs="0" />
+                        <xs:element name="comment" type="xs:string" minOccurs="0" />
+                        <xs:element name="exportmacro" type="xs:string" minOccurs="0" />
+                        <xs:element name="class" type="xs:string" />
+                        <xs:element name="widget" type="Widget" />
+                        <xs:element name="layoutdefault" type="LayoutDefault" minOccurs="0" />
+                        <xs:element name="layoutfunction" type="LayoutFunction" minOccurs="0" />
+                        <xs:element name="pixmapfunction" type="xs:string" minOccurs="0" />
+                        <xs:element name="customwidgets" type="CustomWidgets" minOccurs="0" />
+                        <xs:element name="tabstops" type="TabStops" minOccurs="0" />
+                        <xs:element name="images" type="Images" minOccurs="0" />
+                        <xs:element name="includes" type="Includes" minOccurs="0" />
+                        <xs:element name="resources" type="Resources" minOccurs="0" />
+                        <xs:element name="connections" type="Connections" minOccurs="0" />
+                        <xs:element name="designerdata" type="DesignerData" minOccurs="0" />
+                        <xs:element name="slots" type="Slots" minOccurs="0" />
+                        <xs:element name="buttongroups" type="ButtonGroups" minOccurs="0" />
+                </xs:all>
+                <xs:attribute name="version" type="xs:string" use="required" />
+                <xs:attribute name="language" type="xs:string" />
+                <xs:attribute name="displayname" type="xs:string" />
+<!-- Legacy attribute generated by uic3 -->
+                <xs:attribute name="stdsetdef" type="xs:integer" />
+<!-- Legacy attribute generated by the VS integration -->
+                <xs:attribute name="stdSetDef" type="xs:integer" />
+        </xs:complexType>
+
+<!-- include begin -->
+        <xs:complexType name="Includes">
+            <xs:sequence>
+                        <xs:element name="include" type="Include" maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Include" mixed="true" >
+                <xs:attribute name="location" type="xs:string" use="required" />
+                <xs:attribute name="impldecl" type="xs:string" />
+        </xs:complexType>
+<!-- include end -->
+
+<!-- resource begin -->
+        <xs:complexType name="Resources">
+            <xs:sequence>
+                        <xs:element name="include" type="Resource" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+                <xs:attribute name="name" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="Resource">
+                <xs:attribute name="location" type="xs:string" use="required" />
+        </xs:complexType>
+<!-- resource end -->
+
+<!-- actions begin -->
+        <xs:complexType name="ActionGroup">
+                <xs:sequence maxOccurs="unbounded">
+                        <xs:element name="action" type="Action" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="actiongroup" type="ActionGroup" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="name" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="Action">
+                <xs:sequence maxOccurs="unbounded" >
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="name" type="xs:string" use="required" />
+                <xs:attribute name="menu" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="ActionRef">
+                <xs:attribute name="name" type="xs:string" use="required" />
+        </xs:complexType>
+<!-- actions end -->
+
+<!-- button groups begin -->
+        <xs:complexType name="ButtonGroup">
+                <xs:sequence maxOccurs="unbounded">
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="name" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="ButtonGroups">
+            <xs:sequence>
+                        <xs:element name="buttongroup" type="ButtonGroup" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+<!--  button groups end -->
+
+<!-- images begin -->
+        <xs:complexType name="Images">
+            <xs:sequence>
+                        <xs:element name="image" type="Image" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Image">
+            <xs:sequence>
+                        <xs:element name="data" type="ImageData" />
+        </xs:sequence>
+                <xs:attribute name="name" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="ImageData" mixed="true" >
+                <xs:attribute name="format" type="xs:string" use="required" />
+                <xs:attribute name="length" type="xs:integer" use="required" />
+        </xs:complexType>
+<!-- images end -->
+
+<!-- custom widget support begin -->
+        <xs:complexType name="CustomWidgets">
+            <xs:sequence>
+                        <xs:element name="customwidget" type="CustomWidget" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Header" mixed="true" >
+                <xs:attribute name="location" type="xs:string" />  <!-- local or global -->
+        </xs:complexType>
+
+        <xs:complexType name="CustomWidget">
+                <xs:all>
+                        <xs:element name="class" type="xs:string" />
+                        <xs:element name="extends" type="xs:string" />
+                        <xs:element name="header" type="Header" />
+                        <xs:element name="sizehint" type="Size" minOccurs="0" />
+                        <xs:element name="addpagemethod" type="xs:string" minOccurs="0" />
+                        <xs:element name="container" type="xs:integer" minOccurs="0" />
+                        <xs:element name="sizepolicy" type="SizePolicyData" minOccurs="0" />
+                        <xs:element name="pixmap" type="xs:string" minOccurs="0" />
+                        <xs:element name="script" type="Script" minOccurs="0" />
+                        <xs:element name="properties" type="Properties" minOccurs="0" />
+                        <xs:element name="slots" type="Slots" minOccurs="0" />
+                        <xs:element name="propertyspecifications" type="PropertySpecifications" minOccurs="0" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Properties">
+            <xs:sequence>
+                        <xs:element name="property" type="PropertyData" maxOccurs="unbounded" />
+                </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="PropertyData">
+                <xs:attribute name="type" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="SizePolicyData">
+                <xs:all>
+                        <xs:element name="hordata" type="xs:integer" />
+                        <xs:element name="verdata" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+<!-- custom widget support end -->
+
+        <xs:complexType name="LayoutDefault">
+                <xs:attribute name="spacing" type="xs:integer" use="required" />
+                <xs:attribute name="margin" type="xs:integer" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="LayoutFunction">
+                <xs:attribute name="spacing" type="xs:string" use="required" />
+                <xs:attribute name="margin" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="TabStops">
+                <xs:sequence>
+                        <xs:element name="tabstop" type="xs:string" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Layout">
+                <xs:sequence maxOccurs="unbounded" >
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="item" type="LayoutItem" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="class" type="xs:string" use="required" />
+                <xs:attribute name="name" type="xs:string" />
+                <xs:attribute name="stretch" type="xs:string" />
+                <xs:attribute name="rowstretch" type="xs:string" />
+                <xs:attribute name="columnstretch" type="xs:string" />
+                <xs:attribute name="rowminimumheight" type="xs:string" />
+                <xs:attribute name="columnminimumwidth" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="LayoutItem">
+                <xs:choice>
+                        <xs:element name="widget" type="Widget" />
+                        <xs:element name="layout" type="Layout" />
+                        <xs:element name="spacer" type="Spacer" />
+                </xs:choice>
+                <xs:attribute name="row" type="xs:integer" />
+                <xs:attribute name="column" type="xs:integer" />
+                <xs:attribute name="rowspan" type="xs:integer" />
+                <xs:attribute name="colspan" type="xs:integer" />
+               <xs:attribute name="alignment" type="xs:string" />
+        </xs:complexType>
+
+<!-- item view begin -->
+        <xs:complexType name="Row">
+            <xs:sequence>
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Column">
+            <xs:sequence>
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Item">
+                <xs:sequence maxOccurs="unbounded">
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="item" type="Item" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="row" type="xs:integer" />
+                <xs:attribute name="column" type="xs:integer" />
+        </xs:complexType>
+<!-- item view end -->
+
+        <xs:complexType name="Widget">
+            <!-- Order does not matter (cannot use xs:all here
+                     because of unbounded row, column, item -->
+                <xs:sequence>
+                        <xs:element name="class" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+                        <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="script" type="Script"  minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+                        <xs:element name="widgetdata" type="WidgetData"  minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+                        <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+<!-- item view begin -->
+                        <xs:element name="row" type="Row" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="column" type="Column"  minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="item" type="Item" minOccurs="0" maxOccurs="unbounded" />
+<!-- item view end -->
+                        <xs:element name="layout" type="Layout" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+                        <xs:element name="widget" type="Widget" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="action" type="Action" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="actiongroup" type="ActionGroup" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="addaction" type="ActionRef" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="zorder" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+                <xs:attribute name="class" type="xs:string" use="required" />
+                <xs:attribute name="name" type="xs:string" />
+                <xs:attribute name="native" type="xs:boolean" />
+        </xs:complexType>
+
+        <xs:complexType name="Spacer">
+            <xs:sequence>
+                        <xs:element name="property" type="Property" maxOccurs="unbounded" />
+        </xs:sequence>
+                <xs:attribute name="name" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="Color">
+                <xs:all>
+                    <xs:element name="red" type="xs:integer" />
+                    <xs:element name="green" type="xs:integer" />
+                    <xs:element name="blue" type="xs:integer" />
+                </xs:all>
+                <xs:attribute name="alpha" type="xs:integer" />
+        </xs:complexType>
+
+        <xs:complexType name="GradientStop">
+            <xs:sequence>
+                        <xs:element name="color" type="Color" />
+            </xs:sequence>
+                <xs:attribute name="position" type="xs:double" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="Gradient">
+            <xs:sequence>
+                        <xs:element name="gradientStop" type="GradientStop" maxOccurs="unbounded" />
+            </xs:sequence>
+                <xs:attribute name="startx" type="xs:double" use="required" />
+                <xs:attribute name="starty" type="xs:double" use="required" />
+                <xs:attribute name="endx" type="xs:double" use="required" />
+                <xs:attribute name="endy" type="xs:double" use="required" />
+                <xs:attribute name="centralx" type="xs:double" use="required" />
+                <xs:attribute name="centraly" type="xs:double" use="required" />
+                <xs:attribute name="focalx" type="xs:double" use="required" />
+                <xs:attribute name="focaly" type="xs:double" use="required" />
+                <xs:attribute name="radius" type="xs:double" use="required" />
+                <xs:attribute name="angle" type="xs:double" use="required" />
+                <xs:attribute name="type" type="xs:string" use="required" />
+                <xs:attribute name="spread" type="xs:string" use="required" />
+                <xs:attribute name="coordinatemode" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="Brush">
+                <xs:choice>
+                    <xs:element name="color" type="Color" />
+                    <xs:element name="texture" type="Property" />
+                    <xs:element name="gradient" type="Gradient" />
+                </xs:choice>
+                <xs:attribute name="brushstyle" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="ColorRole">
+            <xs:sequence>
+                        <xs:element name="brush" type="Brush" />
+            </xs:sequence>
+                <xs:attribute name="role" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="ColorGroup">
+                <xs:sequence maxOccurs="unbounded">
+                        <xs:element name="colorrole" type="ColorRole" minOccurs="0" maxOccurs="unbounded" />
+                        <xs:element name="color" type="Color" minOccurs="0" maxOccurs="unbounded" />
+                </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Palette">
+                <xs:all>
+                        <xs:element name="active" type="ColorGroup" />
+                        <xs:element name="inactive" type="ColorGroup" />
+                        <xs:element name="disabled" type="ColorGroup" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Font">
+                <xs:all>
+                        <xs:element name="family" type="xs:string" minOccurs="0" />
+                        <xs:element name="pointsize" type="xs:integer" minOccurs="0" />
+                        <xs:element name="weight" type="xs:integer" minOccurs="0" />
+                        <xs:element name="italic" type="xs:boolean" minOccurs="0" />
+                        <xs:element name="bold" type="xs:boolean" minOccurs="0" />
+                        <xs:element name="underline" type="xs:boolean" minOccurs="0" />
+                        <xs:element name="strikeout" type="xs:boolean" minOccurs="0" />
+                        <xs:element name="antialiasing" type="xs:boolean" minOccurs="0" />
+                        <xs:element name="stylestrategy" type="xs:string" minOccurs="0" />
+                        <xs:element name="kerning" type="xs:boolean" minOccurs="0" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Point">
+                <xs:all>
+                        <xs:element name="x" type="xs:integer" />
+                        <xs:element name="y" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Rect">
+                <xs:all>
+                        <xs:element name="x" type="xs:integer" />
+                        <xs:element name="y" type="xs:integer" />
+                        <xs:element name="width" type="xs:integer" />
+                        <xs:element name="height" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Locale">
+                <xs:attribute name="language" type="xs:string" use="required" />
+                <xs:attribute name="country" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="SizePolicy">
+                <xs:all>
+                        <xs:element name="hsizetype" type="xs:integer" minOccurs="0" />
+                        <xs:element name="vsizetype" type="xs:integer" minOccurs="0" />
+                        <xs:element name="horstretch" type="xs:integer" />
+                        <xs:element name="verstretch" type="xs:integer" />
+                </xs:all>
+                <xs:attribute name="hsizetype" type="xs:string" />
+                <xs:attribute name="vsizetype" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="Size">
+                <xs:all>
+                        <xs:element name="width" type="xs:integer" />
+                        <xs:element name="height" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Date">
+                <xs:all>
+                        <xs:element name="year" type="xs:integer" />
+                        <xs:element name="month" type="xs:integer" />
+                        <xs:element name="day" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Time">
+                <xs:all>
+                        <xs:element name="hour" type="xs:integer" />
+                        <xs:element name="minute" type="xs:integer" />
+                        <xs:element name="second" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="DateTime">
+                <xs:all>
+                        <xs:element name="hour" type="xs:integer" />
+                        <xs:element name="minute" type="xs:integer" />
+                        <xs:element name="second" type="xs:integer" />
+                        <xs:element name="year" type="xs:integer" />
+                        <xs:element name="month" type="xs:integer" />
+                        <xs:element name="day" type="xs:integer" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="StringList">
+            <xs:sequence>
+                        <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="ResourcePixmap" mixed="true">
+                <xs:attribute name="resource" type="xs:string" />
+                <xs:attribute name="alias" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="ResourceIcon" mixed="true">
+                <xs:all>
+                        <xs:element name="normaloff" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="normalon" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="disabledoff" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="disabledon" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="activeoff" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="activeon" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="selectedoff" type="ResourcePixmap" minOccurs="0" />
+                        <xs:element name="selectedon" type="ResourcePixmap" minOccurs="0" />
+                </xs:all>
+               <xs:attribute name="theme" type="xs:string" />
+                <xs:attribute name="resource" type="xs:string" /> <!-- pre 4.4 legacy support -->
+        </xs:complexType>
+
+        <xs:complexType name="String" mixed="true">
+                <xs:attribute name="notr" type="xs:string" />
+                <xs:attribute name="comment" type="xs:string" />
+                <xs:attribute name="extracomment" type="xs:string" />
+        </xs:complexType>
+
+        <xs:complexType name="PointF">
+                <xs:all>
+                        <xs:element name="x" type="xs:double" />
+                        <xs:element name="y" type="xs:double" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="RectF">
+                <xs:all>
+                        <xs:element name="x" type="xs:double" />
+                        <xs:element name="y" type="xs:double" />
+                        <xs:element name="width" type="xs:double" />
+                        <xs:element name="height" type="xs:double" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="SizeF">
+                <xs:all>
+                        <xs:element name="width" type="xs:double" />
+                        <xs:element name="height" type="xs:double" />
+                </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="Char">
+            <xs:sequence>
+                        <xs:element name="unicode" type="xs:integer" />
+            </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Url">
+            <xs:sequence>
+                        <xs:element name="string" type="String" />
+            </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Property">
+                <xs:choice>
+                        <xs:element name="bool" type="xs:string" />
+                        <xs:element name="color" type="Color" />
+                        <xs:element name="cstring" type="xs:string" />
+                        <xs:element name="cursor" type="xs:integer" />
+                        <xs:element name="cursorshape" type="xs:string" />
+                        <xs:element name="enum" type="xs:string" />
+                        <xs:element name="font" type ="Font" />
+                        <xs:element name="iconset" type="ResourceIcon"/>
+                        <xs:element name="pixmap" type="ResourcePixmap" />
+                        <xs:element name="palette" type="Palette" />
+                        <xs:element name="point" type="Point" />
+                        <xs:element name="rect" type="Rect" />
+                        <xs:element name="set" type="xs:string" />
+                        <xs:element name="locale" type="Locale" />
+                        <xs:element name="sizepolicy" type="SizePolicy" />
+                        <xs:element name="size" type="Size" />
+                        <xs:element name="string" type="String" />
+                        <xs:element name="stringlist" type="StringList" />
+                        <xs:element name="number" type="xs:integer" />
+                        <xs:element name="float" type="xs:float" />
+                        <xs:element name="double" type="xs:double" />
+                        <xs:element name="date" type="Date" />
+                        <xs:element name="time" type="Time" />
+                        <xs:element name="datetime" type="DateTime" />
+                        <xs:element name="pointf" type="PointF" />
+                        <xs:element name="rectf" type="RectF" />
+                        <xs:element name="sizef" type="SizeF" />
+                        <xs:element name="longlong" type="xs:long" />
+                        <xs:element name="char" type="Char" />
+                        <xs:element name="url" type="Url" />
+                        <xs:element name="uint" type="xs:unsignedInt" />
+                        <xs:element name="ulonglong" type="xs:unsignedLong" />
+                        <xs:element name="brush" type="Brush" />
+                </xs:choice>
+                <xs:attribute name="name" type="xs:string" use="required" />
+                <xs:attribute name="stdset" type="xs:integer" />
+        </xs:complexType>
+
+        <xs:complexType name="Connections">
+            <xs:sequence>
+                        <xs:element name="connection" type="Connection" minOccurs="0" maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Connection">
+            <xs:all>
+                <xs:element name="sender" type="xs:string" />
+                <xs:element name="signal" type="xs:string" />
+                <xs:element name="receiver" type="xs:string" />
+                <xs:element name="slot" type="xs:string" />
+                <xs:element name="hints" type="ConnectionHints" minOccurs="0" />
+            </xs:all>
+        </xs:complexType>
+
+        <xs:complexType name="ConnectionHints">
+            <xs:sequence>
+                        <xs:element name="hint" type="ConnectionHint" maxOccurs="unbounded" />
+               </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="ConnectionHint">
+            <xs:all>
+                <xs:element name="x" type="xs:integer"/>
+                <xs:element name="y" type="xs:integer"/>
+            </xs:all>
+            <xs:attribute name="type" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="Script">
+            <xs:attribute name="source"   type="xs:string" use="required" />
+            <xs:attribute name="language" type="xs:string" use="required" />
+        </xs:complexType>
+
+        <xs:complexType name="WidgetData">
+            <xs:sequence>
+                <xs:element name="property" type="Property" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="DesignerData">
+            <xs:sequence>
+                <xs:element name="property" type="Property" maxOccurs="unbounded" />
+        </xs:sequence>
+        </xs:complexType>
+
+        <xs:complexType name="Slots">
+            <xs:sequence maxOccurs="unbounded">
+                <xs:element name="signal" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+                <xs:element name="slot" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+
+         <xs:complexType name="PropertySpecifications">
+            <xs:sequence maxOccurs="unbounded">
+                <xs:element name="stringpropertyspecification" type="StringPropertySpecification" minOccurs="0" maxOccurs="unbounded" />
+            </xs:sequence>
+        </xs:complexType>
+
+         <xs:complexType name="StringPropertySpecification">
+                <xs:attribute name="name" type="xs:string" use="required" />
+                <xs:attribute name="type" type="xs:string" use="required" />
+                <xs:attribute name="notr" type="xs:string"/>
+        </xs:complexType>
+
+</xs:schema>
diff --git a/src/designer/designer/CMakeLists.txt b/src/designer/designer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3818390
--- /dev/null
@@ -0,0 +1,104 @@
+add_definitions(
+    ${SHAREDDEVICESKIN_DEFINITIONS}
+)
+set(EXTRA_DESIGNERBIN_LIBS KtCore KtGui KtNetwork KtDesigner KtDesignerComponents)
+
+include(fontpanel/fontpanel.cmake)
+include(qttoolbardialog/qttoolbardialog.cmake)
+
+include_directories(
+    ${CMAKE_BINARY_DIR}/include
+    ${CMAKE_BINARY_DIR}/privateinclude
+    ${CMAKE_BINARY_DIR}/include/QtCore
+    ${CMAKE_BINARY_DIR}/privateinclude/QtCore
+    ${CMAKE_BINARY_DIR}/include/QtGui
+    ${CMAKE_BINARY_DIR}/privateinclude/QtGui
+    ${CMAKE_BINARY_DIR}/include/QtNetwork
+    ${CMAKE_BINARY_DIR}/privateinclude/QtNetwork
+    ${CMAKE_BINARY_DIR}/include/QtDesigner
+    ${CMAKE_BINARY_DIR}/privateinclude/QtDesigner
+    ${CMAKE_BINARY_DIR}/include/QtDesignerComponents
+    ${CMAKE_BINARY_DIR}/privateinclude/QtDesignerComponents
+    ${CMAKE_BINARY_DIR}/include/QtUiTools
+    ${CMAKE_BINARY_DIR}/privateinclude/QtUiTools
+    ${CMAKE_CURRENT_SOURCE_DIR}/fontpanel
+    ${CMAKE_CURRENT_SOURCE_DIR}/qttoolbardialog
+    ${CMAKE_CURRENT_BINARY_DIR}/fontpanel
+    ${CMAKE_CURRENT_BINARY_DIR}/qttoolbardialog
+    ${CMAKE_SOURCE_DIR}/src/designer/sdk
+    ${CMAKE_SOURCE_DIR}/src/designer/extension
+    ${CMAKE_SOURCE_DIR}/src/designer/shared
+    ${CMAKE_SOURCE_DIR}/src/designer
+    ${SHAREDDEVICESKIN_INCLUDES}
+)
+
+set(DESIGNERBIN_HEADERS
+    ${DESIGNERBIN_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_toolwindow.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_formwindow.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_workbench.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_settings.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_actions.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_server.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_appearanceoptions.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/saveformastemplate.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/newform.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/versiondialog.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/designer_enums.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/appfontdialog.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/preferencesdialog.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/assistantclient.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.h
+    ${SHAREDDEVICESKIN_HEADERS}
+)
+
+set(DESIGNERBIN_SOURCES
+    ${DESIGNERBIN_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_toolwindow.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_formwindow.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_workbench.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_settings.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_server.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_actions.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_appearanceoptions.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/saveformastemplate.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/newform.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/versiondialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/appfontdialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/preferencesdialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/assistantclient.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/saveformastemplate.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/preferencesdialog.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/qdesigner_appearanceoptions.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/designer.qrc
+)
+
+if(NOT ${KATIE_TYPE} STREQUAL SHARED)
+    add_definitions(-DQT_DESIGNER_STATIC)
+endif()
+
+if(UNIX AND NOT ${KATIE_PLATFORM} STREQUAL "mac")
+    set(EXTRA_DESIGNERBIN_LIBS
+        ${EXTRA_DESIGNERBIN_LIBS}
+        m
+    )
+endif()
+
+katie_resources(${DESIGNERBIN_SOURCES} ${DESIGNERBIN_HEADERS})
+katie_setup_flags()
+
+add_executable(designer
+    $<TARGET_OBJECTS:shareddeviceskin>
+    ${DESIGNERBIN_SOURCES} ${DESIGNERBIN_HEADERS}
+)
+target_link_libraries(designer ${EXTRA_DESIGNERBIN_LIBS})
+
+install(
+    TARGETS designer
+    RUNTIME DESTINATION ${QT_BINARIES_PATH_INST}
+    COMPONENT Devel
+)
diff --git a/src/designer/designer/Info_mac.plist b/src/designer/designer/Info_mac.plist
new file mode 100644 (file)
index 0000000..b354932
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+        <key>CFBundleIconFile</key>
+        <string>@ICON@</string>
+        <key>CFBundlePackageType</key>
+        <string>APPL</string>
+        <key>CFBundleGetInfoString</key>
+        <string>Created by Qt/QMake</string>
+        <key>CFBundleIdentifier</key>
+        <string>com.trolltech.Designer</string>
+        <key>CFBundleSignature</key>
+        <string>ttxt</string>
+        <key>CFBundleExecutable</key>
+        <string>@EXECUTABLE@</string>
+        <key>CFBundleDocumentTypes</key>
+        <array>
+                <dict>
+                        <key>CFBundleTypeExtensions</key>
+                        <array>
+                                <string>ui</string>
+                        </array>
+                        <key>CFBundleTypeIconFile</key>
+                        <string>uifile.icns</string>
+                        <key>CFBundleTypeRole</key>
+                        <string>Editor</string>
+                        <key>LSIsAppleDefaultForType</key>
+                        <true/>
+                </dict>
+        </array>
+        <key>NOTE</key>
+        <string>Qt/Designer by The Qt Company Ltd</string>
+</dict>
+</plist>
diff --git a/src/designer/designer/appfontdialog.cpp b/src/designer/designer/appfontdialog.cpp
new file mode 100644 (file)
index 0000000..aa3b178
--- /dev/null
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "appfontdialog.h"
+
+#include <iconloader_p.h>
+#include <abstractsettings_p.h>
+
+#include <QtGui/QTreeView>
+#include <QtGui/QToolButton>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QFileDialog>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QDialogButtonBox>
+
+#include <QtCore/QSettings>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/QFileInfo>
+#include <QtCore/qalgorithms.h>
+#include <QtCore/QVector>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+enum {FileNameRole = Qt::UserRole + 1, IdRole =  Qt::UserRole + 2 };
+enum { debugAppFontWidget = 0 };
+
+static const char fontFileKeyC[] = "fontFiles";
+
+// AppFontManager: Singleton that maintains the mapping of loaded application font
+// ids to the file names (which are not stored in QFontDatabase)
+// and provides API for loading/unloading fonts as well for saving/restoring settings.
+
+class AppFontManager
+{
+    Q_DISABLE_COPY(AppFontManager)
+    AppFontManager();
+public:
+    static AppFontManager &instance();
+
+    void save(QDesignerSettingsInterface *s, const QString &prefix) const;
+    void restore(const QDesignerSettingsInterface *s, const QString &prefix);
+
+    // Return id or -1
+    int add(const QString &fontFile, QString *errorMessage);
+
+    bool remove(int id, QString *errorMessage);
+    bool remove(const QString &fontFile, QString *errorMessage);
+    bool removeAt(int index, QString *errorMessage);
+
+    // Store loaded fonts as pair of file name and Id
+    typedef QPair<QString,int> FileNameFontIdPair;
+    typedef QList<FileNameFontIdPair> FileNameFontIdPairs;
+    const FileNameFontIdPairs &fonts() const;
+
+private:
+    FileNameFontIdPairs m_fonts;
+};
+
+AppFontManager::AppFontManager()
+{
+}
+
+AppFontManager &AppFontManager::instance()
+{
+    static AppFontManager rc;
+    return rc;
+}
+
+void AppFontManager::save(QDesignerSettingsInterface *s, const QString &prefix) const
+{
+    // Store as list of file names
+    QStringList fontFiles;
+    const FileNameFontIdPairs::const_iterator cend = m_fonts.constEnd();
+    for (FileNameFontIdPairs::const_iterator it = m_fonts.constBegin(); it != cend; ++it)
+        fontFiles.push_back(it->first);
+
+    s->beginGroup(prefix);
+    s->setValue(QLatin1String(fontFileKeyC),  fontFiles);
+    s->endGroup();
+
+    if (debugAppFontWidget)
+        qDebug() << "AppFontManager::saved" << fontFiles.size() << "fonts under " << prefix;
+}
+
+void AppFontManager::restore(const QDesignerSettingsInterface *s, const QString &prefix)
+{
+    QString key = prefix;
+    key += QLatin1Char('/');
+    key += QLatin1String(fontFileKeyC);
+    const QStringList fontFiles = s->value(key, QStringList()).toStringList();
+
+    if (debugAppFontWidget)
+        qDebug() << "AppFontManager::restoring" << fontFiles.size() << "fonts from " << prefix;
+    if (!fontFiles.empty()) {
+        QString errorMessage;
+        const QStringList::const_iterator cend = fontFiles.constEnd();
+        for (QStringList::const_iterator it = fontFiles.constBegin(); it != cend; ++it)
+            if (add(*it, &errorMessage) == -1)
+                qWarning("%s", qPrintable(errorMessage));
+    }
+}
+
+int AppFontManager::add(const QString &fontFile, QString *errorMessage)
+{
+    const QFileInfo inf(fontFile);
+    if (!inf.isFile()) {
+        *errorMessage = QCoreApplication::translate("AppFontManager", "'%1' is not a file.").arg(fontFile);
+        return -1;
+    }
+    if (!inf.isReadable()) {
+        *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' does not have read permissions.").arg(fontFile);
+        return -1;
+    }
+    const QString fullPath = inf.absoluteFilePath();
+    // Check if already loaded
+    const FileNameFontIdPairs::const_iterator cend = m_fonts.constEnd();
+    for (FileNameFontIdPairs::const_iterator it = m_fonts.constBegin(); it != cend; ++it) {
+        if (it->first == fullPath) {
+            *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' is already loaded.").arg(fontFile);
+            return -1;
+        }
+    }
+
+    const int id = QFontDatabase::addApplicationFont(fullPath);
+    if (id == -1) {
+        *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' could not be loaded.").arg(fontFile);
+        return -1;
+    }
+
+    if (debugAppFontWidget)
+        qDebug() << "AppFontManager::add" << fontFile << id;
+    m_fonts.push_back(FileNameFontIdPair(fullPath, id));
+    return id;
+}
+
+bool AppFontManager::remove(int id, QString *errorMessage)
+{
+    const int count = m_fonts.size();
+    for (int i = 0; i < count; i++)
+        if (m_fonts[i].second == id)
+            return removeAt(i, errorMessage);
+
+    *errorMessage = QCoreApplication::translate("AppFontManager", "'%1' is not a valid font id.").arg(id);
+    return false;
+}
+
+bool AppFontManager::remove(const QString &fontFile, QString *errorMessage)
+{
+    const int count = m_fonts.size();
+    for (int i = 0; i < count; i++)
+        if (m_fonts[i].first == fontFile)
+            return removeAt(i, errorMessage);
+
+    *errorMessage = QCoreApplication::translate("AppFontManager", "There is no loaded font matching the id '%1'.").arg(fontFile);
+    return false;
+}
+
+bool AppFontManager::removeAt(int index, QString *errorMessage)
+{
+    Q_ASSERT(index >= 0 && index < m_fonts.size());
+
+    const QString fontFile = m_fonts[index].first;
+    const int id = m_fonts[index].second;
+
+    if (debugAppFontWidget)
+        qDebug() << "AppFontManager::removeAt" << index << '(' <<  fontFile << id << ')';
+
+    if (!QFontDatabase::removeApplicationFont(id)) {
+        *errorMessage = QCoreApplication::translate("AppFontManager", "The font '%1' (%2) could not be unloaded.").arg(fontFile).arg(id);
+        return false;
+    }
+    m_fonts.removeAt(index);
+    return true;
+}
+
+const AppFontManager::FileNameFontIdPairs &AppFontManager::fonts() const
+{
+    return  m_fonts;
+}
+
+// ------------- AppFontModel
+class AppFontModel : public QStandardItemModel {
+    Q_DISABLE_COPY(AppFontModel)
+public:
+    AppFontModel(QObject *parent = 0);
+
+    void init(const AppFontManager &mgr);
+    void add(const QString &fontFile, int id);
+    int idAt(const QModelIndex &idx) const;
+};
+
+AppFontModel::AppFontModel(QObject * parent) :
+    QStandardItemModel(parent)
+{
+    setHorizontalHeaderLabels(QStringList(AppFontWidget::tr("Fonts")));
+}
+
+void AppFontModel::init(const AppFontManager &mgr)
+{
+    typedef AppFontManager::FileNameFontIdPairs FileNameFontIdPairs;
+
+    const FileNameFontIdPairs &fonts = mgr.fonts();
+    const FileNameFontIdPairs::const_iterator cend = fonts.constEnd();
+    for (FileNameFontIdPairs::const_iterator it = fonts.constBegin(); it != cend; ++it)
+        add(it->first, it->second);
+}
+
+void AppFontModel::add(const QString &fontFile, int id)
+{
+    const QFileInfo inf(fontFile);
+    // Root item with base name
+    QStandardItem *fileItem = new QStandardItem(inf.completeBaseName());
+    const QString fullPath = inf.absoluteFilePath();
+    fileItem->setData(fullPath, FileNameRole);
+    fileItem->setToolTip(fullPath);
+    fileItem->setData(id, IdRole);
+    fileItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
+
+    appendRow(fileItem);
+    const QStringList families = QFontDatabase::applicationFontFamilies(id);
+    const QStringList::const_iterator cend = families.constEnd();
+    for (QStringList::const_iterator it = families.constBegin(); it != cend; ++it) {
+        QStandardItem *familyItem = new QStandardItem(*it);
+        familyItem->setToolTip(fullPath);
+        familyItem->setFont(QFont(*it));
+        familyItem->setFlags(Qt::ItemIsEnabled);
+        fileItem->appendRow(familyItem);
+    }
+}
+
+int AppFontModel::idAt(const QModelIndex &idx) const
+{
+    if (const QStandardItem *item = itemFromIndex(idx))
+        return item->data(IdRole).toInt();
+    return -1;
+}
+
+// ------------- AppFontWidget
+AppFontWidget::AppFontWidget(QWidget *parent) :
+    QGroupBox(parent),
+    m_view(new QTreeView),
+    m_addButton(new QToolButton),
+    m_removeButton(new QToolButton),
+    m_removeAllButton(new QToolButton),
+    m_model(new AppFontModel(this))
+{
+    m_model->init(AppFontManager::instance());
+    m_view->setModel(m_model);
+    m_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+    m_view->expandAll();
+    connect(m_view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
+
+    m_addButton->setToolTip(tr("Add font files"));
+    m_addButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("plus.png")));
+    connect(m_addButton, SIGNAL(clicked()), this, SLOT(addFiles()));
+
+    m_removeButton->setEnabled(false);
+    m_removeButton->setToolTip(tr("Remove current font file"));
+    m_removeButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("minus.png")));
+    connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveFiles()));
+
+    m_removeAllButton->setToolTip(tr("Remove all font files"));
+    m_removeAllButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("editdelete.png")));
+    connect(m_removeAllButton, SIGNAL(clicked()), this, SLOT(slotRemoveAll()));
+
+    QHBoxLayout *hLayout = new QHBoxLayout;
+    hLayout->addWidget(m_addButton);
+    hLayout->addWidget(m_removeButton);
+    hLayout->addWidget(m_removeAllButton);
+    hLayout->addItem(new QSpacerItem(0, 0,QSizePolicy::MinimumExpanding));
+
+    QVBoxLayout *vLayout = new QVBoxLayout;
+    vLayout->addWidget(m_view);
+    vLayout->addLayout(hLayout);
+    setLayout(vLayout);
+}
+
+void AppFontWidget::addFiles()
+{
+    const QStringList files =
+        QFileDialog::getOpenFileNames(this, tr("Add Font Files"), QString(),
+                                      tr("Font files (*.ttf)"));
+    if (files.empty())
+        return;
+
+    QString errorMessage;
+
+    AppFontManager &fmgr = AppFontManager::instance();
+    const QStringList::const_iterator cend = files.constEnd();
+    for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+        const int id = fmgr.add(*it, &errorMessage);
+        if (id != -1) {
+            m_model->add(*it, id);
+        } else {
+            QMessageBox::critical(this, tr("Error Adding Fonts"), errorMessage);
+        }
+    }
+    m_view->expandAll();
+}
+
+static void removeFonts(const QModelIndexList &selectedIndexes, AppFontModel *model, QWidget *dialogParent)
+{
+    if (selectedIndexes.empty())
+        return;
+
+    // Reverse sort top level rows and remove
+    AppFontManager &fmgr = AppFontManager::instance();
+    QVector<int> rows;
+    rows.reserve(selectedIndexes.size());
+
+    QString errorMessage;
+    const QModelIndexList::const_iterator cend = selectedIndexes.constEnd();
+    for (QModelIndexList::const_iterator it = selectedIndexes.constBegin(); it != cend; ++it) {
+        const int id = model->idAt(*it);
+        if (id != -1) {
+            if (fmgr.remove(id, &errorMessage)) {
+                rows.push_back(it->row());
+            } else {
+                QMessageBox::critical(dialogParent, AppFontWidget::tr("Error Removing Fonts"), errorMessage);
+            }
+        }
+    }
+
+    qStableSort(rows.begin(), rows.end());
+    for (int i = rows.size() - 1; i >= 0; i--)
+        model->removeRow(rows[i]);
+}
+
+void AppFontWidget::slotRemoveFiles()
+{
+    removeFonts(m_view->selectionModel()->selectedIndexes(), m_model, this);
+}
+
+void AppFontWidget::slotRemoveAll()
+{
+    const int count = m_model->rowCount();
+    if (!count)
+        return;
+
+    const QMessageBox::StandardButton answer =
+        QMessageBox::question(this, tr("Remove Fonts"), tr("Would you like to remove all fonts?"),
+                              QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+    if (answer == QMessageBox::No)
+        return;
+
+    QModelIndexList topLevels;
+    for (int i = 0; i < count; i++)
+        topLevels.push_back(m_model->index(i, 0));
+    removeFonts(topLevels, m_model, this);
+}
+
+void AppFontWidget::selectionChanged(const QItemSelection &selected, const QItemSelection & /*deselected*/)
+{
+     m_removeButton->setEnabled(!selected.indexes().empty());
+}
+
+void AppFontWidget::save(QDesignerSettingsInterface *s, const QString &prefix)
+{
+    AppFontManager::instance().save(s, prefix);
+}
+
+void AppFontWidget::restore(const QDesignerSettingsInterface *s, const QString &prefix)
+{
+    AppFontManager::instance().restore(s, prefix);
+}
+
+// ------------ AppFontDialog
+AppFontDialog::AppFontDialog(QWidget *parent) :
+    QDialog(parent),
+    m_appFontWidget(new AppFontWidget)
+{
+    setAttribute(Qt::WA_DeleteOnClose, true);
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+    setWindowTitle(tr("Additional Fonts"));
+    setModal(false);
+    QVBoxLayout *vl = new  QVBoxLayout;
+    vl->addWidget(m_appFontWidget);
+
+    QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Close);
+    QDialog::connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
+    vl->addWidget(bb);
+    setLayout(vl);
+}
+
+QT_END_NAMESPACE
+#include <moc_appfontdialog.h>
diff --git a/src/designer/designer/appfontdialog.h b/src/designer/designer/appfontdialog.h
new file mode 100644 (file)
index 0000000..c4b8674
--- /dev/null
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_APPFONTWIDGET_H
+#define QDESIGNER_APPFONTWIDGET_H
+
+#include <QtGui/QGroupBox>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class AppFontModel;
+
+class QTreeView;
+class QToolButton;
+class QItemSelection;
+class QDesignerSettingsInterface;
+
+// AppFontWidget: Manages application fonts which the user can load and 
+// provides API for saving/restoring them.
+
+class AppFontWidget : public QGroupBox
+{
+    Q_DISABLE_COPY(AppFontWidget)
+    Q_OBJECT
+public:
+    explicit AppFontWidget(QWidget *parent = 0);
+
+    QStringList fontFiles() const;
+
+    static void save(QDesignerSettingsInterface *s, const QString &prefix);
+    static void restore(const QDesignerSettingsInterface *s, const QString &prefix);
+
+private slots:
+    void addFiles();
+    void slotRemoveFiles();
+    void slotRemoveAll();
+    void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
+
+private:
+    QTreeView *m_view;
+    QToolButton *m_addButton;
+    QToolButton *m_removeButton;
+    QToolButton *m_removeAllButton;
+    AppFontModel *m_model;
+};
+
+// AppFontDialog: Non modal dialog for AppFontWidget which has Qt::WA_DeleteOnClose set.
+
+class AppFontDialog : public QDialog
+{
+    Q_DISABLE_COPY(AppFontDialog)
+    Q_OBJECT
+public:
+    explicit AppFontDialog(QWidget *parent = 0);
+
+private:
+    AppFontWidget *m_appFontWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_APPFONTWIDGET_H
diff --git a/src/designer/designer/assistantclient.cpp b/src/designer/designer/assistantclient.cpp
new file mode 100644 (file)
index 0000000..c6ae30e
--- /dev/null
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "assistantclient.h"
+
+#include <QtCore/QString>
+#include <QtCore/QProcess>
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+#include <QtCore/QObject>
+#include <QtCore/QTextStream>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+enum { debugAssistantClient = 0 };
+
+AssistantClient::AssistantClient() :
+    m_process(0)
+{
+}
+
+AssistantClient::~AssistantClient()
+{
+    if (isRunning()) {
+        m_process->terminate();
+        m_process->waitForFinished();
+    }
+    delete m_process;
+}
+
+bool AssistantClient::showPage(const QString &path, QString *errorMessage)
+{
+    QString cmd = QLatin1String("SetSource ");
+    cmd += path;
+    return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::activateIdentifier(const QString &identifier, QString *errorMessage)
+{
+    QString cmd = QLatin1String("ActivateIdentifier ");
+    cmd += identifier;
+    return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::activateKeyword(const QString &keyword, QString *errorMessage)
+{
+    QString cmd = QLatin1String("ActivateKeyword ");
+    cmd += keyword;
+    return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::sendCommand(const QString &cmd, QString *errorMessage)
+{
+    if (debugAssistantClient)
+        qDebug() << "sendCommand " << cmd;
+    if (!ensureRunning(errorMessage))
+        return false;
+    if (!m_process->isWritable() || m_process->bytesToWrite() > 0) {
+        *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to send request: Assistant is not responding.");
+        return false;
+    }
+    QTextStream str(m_process);
+    str << cmd << QLatin1Char('\n') << endl;
+    return true;
+}
+
+bool AssistantClient::isRunning() const
+{
+    return m_process && m_process->state() != QProcess::NotRunning;
+}
+
+QString AssistantClient::binary()
+{
+    QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator();
+#if !defined(Q_OS_MAC)
+    app += QLatin1String("assistant");
+#else
+    app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");    
+#endif
+
+#if defined(Q_OS_WIN)
+    app += QLatin1String(".exe");
+#endif
+
+    return app;
+}
+
+bool AssistantClient::ensureRunning(QString *errorMessage)
+{
+    if (isRunning())
+        return true;
+
+    if (!m_process)
+        m_process = new QProcess;
+
+    const QString app = binary();
+    if (!QFileInfo(app).isFile()) {
+        *errorMessage = QCoreApplication::translate("AssistantClient", "The binary '%1' does not exist.").arg(app);
+        return false;
+    }
+    if (debugAssistantClient)
+        qDebug() << "Running " << app;
+    // run
+    QStringList args(QLatin1String("-enableRemoteControl"));
+    m_process->start(app, args);
+    if (!m_process->waitForStarted()) {
+        *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to launch assistant (%1).").arg(app);
+        return false;
+    }
+    return true;
+}
+
+QString AssistantClient::documentUrl(const QString &prefix, int qtVersion)
+{
+    if (qtVersion == 0)
+        qtVersion = QT_VERSION;
+    QString rc;
+    QTextStream(&rc) << QLatin1String("qthelp://com.trolltech.") << prefix << QLatin1Char('.')
+                     << (qtVersion >> 16) << ((qtVersion >> 8) & 0xFF) << (qtVersion & 0xFF)
+                     << QLatin1String("/qdoc/");
+    return rc;
+}
+
+QString AssistantClient::designerManualUrl(int qtVersion)
+{
+    return documentUrl(QLatin1String("designer"), qtVersion);
+}
+
+QString AssistantClient::qtReferenceManualUrl(int qtVersion)
+{
+    return documentUrl(QLatin1String("qt"), qtVersion);
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/designer/assistantclient.h b/src/designer/designer/assistantclient.h
new file mode 100644 (file)
index 0000000..2b753a7
--- /dev/null
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ASSISTANTCLIENT_H
+#define ASSISTANTCLIENT_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QProcess;
+class QString;
+
+class AssistantClient
+{
+    AssistantClient(const AssistantClient &);
+    AssistantClient &operator=(const AssistantClient &);
+
+public:
+    AssistantClient();
+    ~AssistantClient();
+
+    bool showPage(const QString &path, QString *errorMessage);
+    bool activateIdentifier(const QString &identifier, QString *errorMessage);
+    bool activateKeyword(const QString &keyword, QString *errorMessage);
+
+    bool isRunning() const;
+
+    static QString documentUrl(const QString &prefix, int qtVersion = 0);
+    // Root of the Qt Designer documentation
+    static QString designerManualUrl(int qtVersion = 0);
+    // Root of the Qt Reference documentation
+    static QString qtReferenceManualUrl(int qtVersion = 0);
+
+private:
+    static QString binary();
+    bool sendCommand(const QString &cmd, QString *errorMessage);
+    bool ensureRunning(QString *errorMessage);
+
+    QProcess *m_process;
+};
+
+QT_END_NAMESPACE
+
+#endif // ASSISTANTCLIENT_H
diff --git a/src/designer/designer/designer.icns b/src/designer/designer/designer.icns
new file mode 100644 (file)
index 0000000..9940214
Binary files /dev/null and b/src/designer/designer/designer.icns differ
diff --git a/src/designer/designer/designer.ico b/src/designer/designer/designer.ico
new file mode 100644 (file)
index 0000000..ef66733
Binary files /dev/null and b/src/designer/designer/designer.ico differ
diff --git a/src/designer/designer/designer.pro b/src/designer/designer/designer.pro
new file mode 100644 (file)
index 0000000..9c59b67
--- /dev/null
@@ -0,0 +1,13 @@
+win32 {
+   RC_FILE      = designer.rc
+}
+
+mac {
+    ICON = designer.icns
+    QMAKE_INFO_PLIST = Info_mac.plist
+    TARGET = Designer
+    FILETYPES.files = uifile.icns
+    FILETYPES.path = Contents/Resources
+    QMAKE_BUNDLE_DATA += FILETYPES
+}
+
diff --git a/src/designer/designer/designer.qrc b/src/designer/designer/designer.qrc
new file mode 100644 (file)
index 0000000..fac8120
--- /dev/null
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+    <qresource prefix="/trolltech/designer">
+        <file>images/designer.png</file>
+    </qresource>
+</RCC>
diff --git a/src/designer/designer/designer.rc b/src/designer/designer/designer.rc
new file mode 100644 (file)
index 0000000..e43943a
--- /dev/null
@@ -0,0 +1,32 @@
+#include "winver.h"
+
+IDI_ICON1               ICON    DISCARDABLE     "designer.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGS 0x0L
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "CompanyName", "The Qt Company Ltd"
+            VALUE "FileDescription", "Qt Designer"
+            VALUE "FileVersion", "1.0.0.0"
+            VALUE "LegalCopyright", "Copyright (C) 2015 The Qt Company Ltd."
+            VALUE "InternalName", "designer"
+            VALUE "OriginalFilename", "designer.exe"
+            VALUE "ProductName", "Qt Designer"
+            VALUE "ProductVersion", "1.0.0.0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
diff --git a/src/designer/designer/designer_enums.h b/src/designer/designer/designer_enums.h
new file mode 100644 (file)
index 0000000..7908af0
--- /dev/null
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERENUMS_H
+#define DESIGNERENUMS_H
+
+enum UIMode
+{
+    NeutralMode,
+    TopLevelMode,
+    DockedMode
+};
+
+#endif // DESIGNERENUMS_H
diff --git a/src/designer/designer/fontpanel/fontpanel.cmake b/src/designer/designer/fontpanel/fontpanel.cmake
new file mode 100644 (file)
index 0000000..07937c0
--- /dev/null
@@ -0,0 +1,9 @@
+set(DESIGNERBIN_SOURCES
+    ${DESIGNERBIN_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/fontpanel/fontpanel.cpp
+)
+
+set(DESIGNERBIN_HEADERS
+    ${DESIGNERBIN_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/fontpanel/fontpanel.h
+) 
diff --git a/src/designer/designer/fontpanel/fontpanel.cpp b/src/designer/designer/fontpanel/fontpanel.cpp
new file mode 100644 (file)
index 0000000..f1663c1
--- /dev/null
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fontpanel.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QComboBox>
+#include <QtGui/QFormLayout>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QFontComboBox>
+#include <QtCore/QTimer>
+#include <QtGui/QLineEdit>
+
+QT_BEGIN_NAMESPACE
+
+FontPanel::FontPanel(QWidget *parentWidget) :
+    QGroupBox(parentWidget),
+    m_previewLineEdit(new QLineEdit),
+    m_writingSystemComboBox(new QComboBox),
+    m_familyComboBox(new QFontComboBox),
+    m_styleComboBox(new QComboBox),
+    m_pointSizeComboBox(new QComboBox),
+    m_previewFontUpdateTimer(0)
+{
+    setTitle(tr("Font"));
+
+    QFormLayout *formLayout = new QFormLayout(this);
+    // writing systems
+    m_writingSystemComboBox->setEditable(false);
+
+    QList<QFontDatabase::WritingSystem> writingSystems = m_fontDatabase.writingSystems();
+    writingSystems.push_front(QFontDatabase::Any);
+    foreach (QFontDatabase::WritingSystem ws, writingSystems)
+        m_writingSystemComboBox->addItem(QFontDatabase::writingSystemName(ws), QVariant(ws));
+    connect(m_writingSystemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotWritingSystemChanged(int)));
+    formLayout->addRow(tr("&Writing system"), m_writingSystemComboBox);
+
+    connect(m_familyComboBox, SIGNAL(currentFontChanged(QFont)), this, SLOT(slotFamilyChanged(QFont)));
+    formLayout->addRow(tr("&Family"), m_familyComboBox);
+
+    m_styleComboBox->setEditable(false);
+    connect(m_styleComboBox,  SIGNAL(currentIndexChanged(int)),  this, SLOT(slotStyleChanged(int)));
+    formLayout->addRow(tr("&Style"), m_styleComboBox);
+
+    m_pointSizeComboBox->setEditable(false);
+    connect(m_pointSizeComboBox, SIGNAL(currentIndexChanged(int)),  this, SLOT(slotPointSizeChanged(int)));
+    formLayout->addRow(tr("&Point size"), m_pointSizeComboBox);
+
+    m_previewLineEdit->setReadOnly(true);
+    formLayout->addRow(m_previewLineEdit);
+
+    setWritingSystem(QFontDatabase::Any);
+}
+
+QFont FontPanel::selectedFont() const
+{
+    QFont rc = m_familyComboBox->currentFont();
+    const QString family = rc.family();
+    rc.setPointSize(pointSize());
+    const QString styleDescription = styleString();
+    if (styleDescription.contains(QLatin1String("Italic")))
+        rc.setStyle(QFont::StyleItalic);
+    else if (styleDescription.contains(QLatin1String("Oblique")))
+        rc.setStyle(QFont::StyleOblique);
+    else
+        rc.setStyle(QFont::StyleNormal);
+    rc.setBold(m_fontDatabase.bold(family, styleDescription));
+
+    // Weight < 0 asserts...
+    const int weight = m_fontDatabase.weight(family, styleDescription);
+    if (weight >= 0)
+        rc.setWeight(weight);
+    return rc;
+}
+
+void FontPanel::setSelectedFont(const QFont &f)
+{
+    m_familyComboBox->setCurrentFont(f);
+    if (m_familyComboBox->currentIndex() < 0) {
+        // family not in writing system - find the corresponding one?
+        QList<QFontDatabase::WritingSystem> familyWritingSystems = m_fontDatabase.writingSystems(f.family());
+        if (familyWritingSystems.empty())
+            return;
+
+        setWritingSystem(familyWritingSystems.front());
+        m_familyComboBox->setCurrentFont(f);
+    }
+
+    updateFamily(family());
+
+    const int pointSizeIndex = closestPointSizeIndex(f.pointSize());
+    m_pointSizeComboBox->setCurrentIndex( pointSizeIndex);
+
+    const QString styleString = m_fontDatabase.styleString(f);
+    const int styleIndex = m_styleComboBox->findText(styleString);
+    m_styleComboBox->setCurrentIndex(styleIndex);
+    slotUpdatePreviewFont();
+}
+
+
+QFontDatabase::WritingSystem FontPanel::writingSystem() const
+{
+    const int currentIndex = m_writingSystemComboBox->currentIndex();
+    if ( currentIndex == -1)
+        return QFontDatabase::Latin;
+    return static_cast<QFontDatabase::WritingSystem>(m_writingSystemComboBox->itemData(currentIndex).toInt());
+}
+
+QString FontPanel::family() const
+{
+    const int currentIndex = m_familyComboBox->currentIndex();
+    return currentIndex != -1 ?  m_familyComboBox->currentFont().family() : QString();
+}
+
+int FontPanel::pointSize() const
+{
+    const int currentIndex = m_pointSizeComboBox->currentIndex();
+    return currentIndex != -1 ? m_pointSizeComboBox->itemData(currentIndex).toInt() : 9;
+}
+
+QString FontPanel::styleString() const
+{
+    const int currentIndex = m_styleComboBox->currentIndex();
+    return currentIndex != -1 ? m_styleComboBox->itemText(currentIndex) : QString();
+}
+
+void FontPanel::setWritingSystem(QFontDatabase::WritingSystem ws)
+{
+    m_writingSystemComboBox->setCurrentIndex(m_writingSystemComboBox->findData(QVariant(ws)));
+    updateWritingSystem(ws);
+}
+
+
+void FontPanel::slotWritingSystemChanged(int)
+{
+    updateWritingSystem(writingSystem());
+    delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotFamilyChanged(const QFont &)
+{
+    updateFamily(family());
+    delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotStyleChanged(int)
+{
+    updatePointSizes(family(), styleString());
+    delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotPointSizeChanged(int)
+{
+    delayedPreviewFontUpdate();
+}
+
+void FontPanel::updateWritingSystem(QFontDatabase::WritingSystem ws)
+{
+
+    m_previewLineEdit->setText(QFontDatabase::writingSystemSample(ws));
+    m_familyComboBox->setWritingSystem (ws);
+    // Current font not in WS ... set index 0.
+    if (m_familyComboBox->currentIndex() < 0) {
+        m_familyComboBox->setCurrentIndex(0);
+        updateFamily(family());
+    }
+}
+
+void FontPanel::updateFamily(const QString &family)
+{
+    // Update styles and trigger update of point sizes.
+    // Try to maintain selection or select normal
+    const QString oldStyleString = styleString();
+
+    const QStringList styles = m_fontDatabase.styles(family);
+    const bool hasStyles = !styles.empty();
+
+    m_styleComboBox->setCurrentIndex(-1);
+    m_styleComboBox->clear();
+    m_styleComboBox->setEnabled(hasStyles);
+
+    int normalIndex = -1;
+    const QString normalStyle = QLatin1String("Normal");
+
+    if (hasStyles) {
+        foreach (const QString &style, styles) {
+            // try to maintain selection or select 'normal' preferably
+            const int newIndex = m_styleComboBox->count();
+            m_styleComboBox->addItem(style);
+            if (oldStyleString == style) {
+                m_styleComboBox->setCurrentIndex(newIndex);
+            } else {
+                if (oldStyleString ==  normalStyle)
+                    normalIndex = newIndex;
+            }
+        }
+        if (m_styleComboBox->currentIndex() == -1 && normalIndex != -1)
+            m_styleComboBox->setCurrentIndex(normalIndex);
+    }
+    updatePointSizes(family, styleString());
+}
+
+int FontPanel::closestPointSizeIndex(int desiredPointSize) const
+{
+    //  try to maintain selection or select closest.
+    int closestIndex = -1;
+    int closestAbsError = 0xFFFF;
+
+    const int pointSizeCount = m_pointSizeComboBox->count();
+    for (int i = 0; i < pointSizeCount; i++) {
+        const int itemPointSize = m_pointSizeComboBox->itemData(i).toInt();
+        const int absError = qAbs(desiredPointSize - itemPointSize);
+        if (absError < closestAbsError) {
+            closestIndex  = i;
+            closestAbsError = absError;
+            if (closestAbsError == 0)
+                break;
+        } else {    // past optimum
+            if (absError > closestAbsError) {
+                break;
+            }
+        }
+    }
+    return closestIndex;
+}
+
+
+void FontPanel::updatePointSizes(const QString &family, const QString &styleString)
+{
+    const int oldPointSize = pointSize();
+
+    QList<int> pointSizes =  m_fontDatabase.pointSizes(family, styleString);
+    if (pointSizes.empty())
+        pointSizes = QFontDatabase::standardSizes();
+
+    const bool hasSizes = !pointSizes.empty();
+    m_pointSizeComboBox->clear();
+    m_pointSizeComboBox->setEnabled(hasSizes);
+    m_pointSizeComboBox->setCurrentIndex(-1);
+
+    //  try to maintain selection or select closest.
+    if (hasSizes) {
+        QString n;
+        foreach (int pointSize, pointSizes)
+            m_pointSizeComboBox->addItem(n.setNum(pointSize), QVariant(pointSize));
+        const int closestIndex = closestPointSizeIndex(oldPointSize);
+        if (closestIndex != -1)
+            m_pointSizeComboBox->setCurrentIndex(closestIndex);
+    }
+}
+
+void FontPanel::slotUpdatePreviewFont()
+{
+    m_previewLineEdit->setFont(selectedFont());
+}
+
+void FontPanel::delayedPreviewFontUpdate()
+{
+    if (!m_previewFontUpdateTimer) {
+        m_previewFontUpdateTimer = new QTimer(this);
+        connect(m_previewFontUpdateTimer, SIGNAL(timeout()), this, SLOT(slotUpdatePreviewFont()));
+        m_previewFontUpdateTimer->setInterval(0);
+        m_previewFontUpdateTimer->setSingleShot(true);
+    }
+    if (m_previewFontUpdateTimer->isActive())
+        return;
+    m_previewFontUpdateTimer->start();
+}
+
+QT_END_NAMESPACE
+#include <moc_fontpanel.h>
diff --git a/src/designer/designer/fontpanel/fontpanel.h b/src/designer/designer/fontpanel/fontpanel.h
new file mode 100644 (file)
index 0000000..7d178b7
--- /dev/null
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of the Qt tools.  This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FONTPANEL_H
+#define FONTPANEL_H
+
+#include <QtGui/QGroupBox>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+class QComboBox;
+class QFontComboBox;
+class QTimer;
+class QLineEdit;
+
+class FontPanel: public QGroupBox
+{
+    Q_OBJECT
+public:
+    FontPanel(QWidget *parentWidget = 0);
+
+    QFont selectedFont() const;
+    void setSelectedFont(const QFont &);
+
+    QFontDatabase::WritingSystem writingSystem() const;
+    void setWritingSystem(QFontDatabase::WritingSystem ws);
+
+private slots:
+    void slotWritingSystemChanged(int);
+    void slotFamilyChanged(const QFont &);
+    void slotStyleChanged(int);
+    void slotPointSizeChanged(int);
+    void slotUpdatePreviewFont();
+
+private:
+    QString family() const;
+    QString styleString() const;
+    int pointSize() const;
+    int closestPointSizeIndex(int ps) const;
+
+    void updateWritingSystem(QFontDatabase::WritingSystem ws);
+    void updateFamily(const QString &family);
+    void updatePointSizes(const QString &family, const QString &style);
+    void delayedPreviewFontUpdate();
+
+    QFontDatabase m_fontDatabase;
+    QLineEdit *m_previewLineEdit;
+    QComboBox *m_writingSystemComboBox;
+    QFontComboBox* m_familyComboBox;
+    QComboBox *m_styleComboBox;
+    QComboBox *m_pointSizeComboBox;
+    QTimer *m_previewFontUpdateTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // FONTPANEL_H
diff --git a/src/designer/designer/images/designer.png b/src/designer/designer/images/designer.png
new file mode 100644 (file)
index 0000000..0988fce
Binary files /dev/null and b/src/designer/designer/images/designer.png differ
diff --git a/src/designer/designer/images/mdi.png b/src/designer/designer/images/mdi.png
new file mode 100644 (file)
index 0000000..5012ab3
Binary files /dev/null and b/src/designer/designer/images/mdi.png differ
diff --git a/src/designer/designer/images/sdi.png b/src/designer/designer/images/sdi.png
new file mode 100644 (file)
index 0000000..7fff6e8
Binary files /dev/null and b/src/designer/designer/images/sdi.png differ
diff --git a/src/designer/designer/images/workbench.png b/src/designer/designer/images/workbench.png
new file mode 100644 (file)
index 0000000..06716a4
Binary files /dev/null and b/src/designer/designer/images/workbench.png differ
diff --git a/src/designer/designer/main.cpp b/src/designer/designer/main.cpp
new file mode 100644 (file)
index 0000000..d00b222
--- /dev/null
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDir>
+
+#include <stdlib.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+    Q_INIT_RESOURCE(designer);
+
+    QDesigner app(argc, argv);
+    app.setQuitOnLastWindowClosed(false);
+
+    return app.exec();
+}
+
+#include <qrc_designer.cpp>
\ No newline at end of file
diff --git a/src/designer/designer/mainwindow.cpp b/src/designer/designer/mainwindow.cpp
new file mode 100644 (file)
index 0000000..2ae2259
--- /dev/null
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_settings.h"
+#include "qttoolbardialog.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#include <QtGui/QAction>
+#include <QtGui/qevent.h>
+#include <QtGui/QToolBar>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QStatusBar>
+#include <QtGui/QMenu>
+#include <QtGui/QLayout>
+#include <QtGui/QDockWidget>
+
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+static const char *uriListMimeFormatC = "text/uri-list";
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QAction *> ActionList;
+
+// Helpers for creating toolbars and menu
+
+static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
+{
+    const ActionList::const_iterator cend = actions.constEnd();
+    for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) {
+        QAction *action = *it;
+        if (action->property(QDesignerActions::defaultToolbarPropertyName).toBool())
+            t->addAction(action);
+    }
+}
+static QToolBar *createToolBar(const QString &title, const QString &objectName, const ActionList &actions)
+{
+    QToolBar *rc =  new QToolBar;
+    rc->setObjectName(objectName);
+    rc->setWindowTitle(title);
+    addActionsToToolBar(actions, rc);
+    return rc;
+}
+
+// ---------------- MainWindowBase
+
+MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) :
+    QMainWindow(parent, flags),
+    m_policy(AcceptCloseEvents)
+{
+#ifndef Q_WS_MAC
+    setWindowIcon(qDesigner->windowIcon());
+#endif
+}
+
+void MainWindowBase::closeEvent(QCloseEvent *e)
+{
+    switch (m_policy) {
+    case AcceptCloseEvents:
+        QMainWindow::closeEvent(e);
+        break;
+      case EmitCloseEventSignal:
+        emit closeEventReceived(e);
+        break;
+    }
+}
+
+QList<QToolBar *>  MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar)
+{
+    // Note that whenever you want to add a new tool bar here, you also have to update the default
+    // action groups added to the toolbar manager in the mainwindow constructor
+    QList<QToolBar *> rc;
+    if (singleToolBar) {
+        //: Not currently used (main tool bar)
+        QToolBar *main = createToolBar(tr("Main"), QLatin1String("mainToolBar"), actions->fileActions()->actions());
+        addActionsToToolBar(actions->editActions()->actions(), main);
+        addActionsToToolBar(actions->toolActions()->actions(), main);
+        addActionsToToolBar(actions->formActions()->actions(), main);
+        rc.push_back(main);
+    } else {
+        rc.push_back(createToolBar(tr("File"), QLatin1String("fileToolBar"), actions->fileActions()->actions()));
+        rc.push_back(createToolBar(tr("Edit"), QLatin1String("editToolBar"),  actions->editActions()->actions()));
+        rc.push_back(createToolBar(tr("Tools"), QLatin1String("toolsToolBar"), actions->toolActions()->actions()));
+        rc.push_back(createToolBar(tr("Form"), QLatin1String("formToolBar"), actions->formActions()->actions()));
+    }
+    return rc;
+}
+
+QString MainWindowBase::mainWindowTitle()
+{
+    return tr("Qt Designer");
+}
+
+// Use the minor Qt version as settings versions to avoid conflicts
+int MainWindowBase::settingsVersion()
+{
+    const int version = QT_VERSION;
+    return (version & 0x00FF00) >> 8;
+}
+
+// ----------------- DockedMdiArea
+
+DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) :
+    QMdiArea(parent),
+    m_extension(extension)
+{
+    setAcceptDrops(true);
+    setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+}
+
+QStringList DockedMdiArea::uiFiles(const QMimeData *d) const
+{
+    // Extract dropped UI files from Mime data.
+    QStringList rc;
+    if (!d->hasFormat(QLatin1String(uriListMimeFormatC)))
+        return rc;
+    const QList<QUrl> urls = d->urls();
+    if (urls.empty())
+        return rc;
+    const QList<QUrl>::const_iterator cend = urls.constEnd();
+    for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
+        const QString fileName = it->toLocalFile();
+        if (!fileName.isEmpty() && fileName.endsWith(m_extension))
+            rc.push_back(fileName);
+    }
+    return rc;
+}
+
+bool DockedMdiArea::event(QEvent *event)
+{
+    // Listen for desktop file manager drop and emit a signal once a file is
+    // dropped.
+    switch (event->type()) {
+    case QEvent::DragEnter: {
+        QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
+        if (!uiFiles(e->mimeData()).empty()) {
+            e->acceptProposedAction();
+            return true;
+        }
+    }
+        break;
+    case QEvent::Drop: {
+        QDropEvent *e = static_cast<QDropEvent*>(event);
+        const QStringList files = uiFiles(e->mimeData());
+        const QStringList::const_iterator cend = files.constEnd();
+        for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+            emit fileDropped(*it);
+        }
+        e->acceptProposedAction();
+        return true;
+    }
+        break;
+    default:
+        break;
+    }
+    return QMdiArea::event(event);
+}
+
+// ------------- ToolBarManager:
+
+static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm)
+{
+    const ActionList::const_iterator cend = al.constEnd();
+    for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
+        tbm->addAction(*it, title);
+}
+
+ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow,
+                                         QWidget *parent,
+                                         QMenu *toolBarMenu,
+                                         const QDesignerActions *actions,
+                                         const QList<QToolBar *> &toolbars,
+                                         const QList<QDesignerToolWindow*> &toolWindows) :
+    QObject(parent),
+    m_configureableMainWindow(configureableMainWindow),
+    m_parent(parent),
+    m_toolBarMenu(toolBarMenu),
+    m_manager(new QtToolBarManager(this)),
+    m_configureAction(new QAction(tr("Configure Toolbars..."), this)),
+    m_toolbars(toolbars)
+{
+    m_configureAction->setMenuRole(QAction::NoRole);
+    m_configureAction->setObjectName(QLatin1String("__qt_configure_tool_bars_action"));
+    connect(m_configureAction, SIGNAL(triggered()), this, SLOT(configureToolBars()));
+
+    m_manager->setMainWindow(configureableMainWindow);
+
+    foreach(QToolBar *tb, m_toolbars) {
+        const QString title = tb->windowTitle();
+        m_manager->addToolBar(tb, title);
+        addActionsToToolBarManager(tb->actions(), title, m_manager);
+    }
+
+    addActionsToToolBarManager(actions->windowActions()->actions(), tr("Window"), m_manager);
+    addActionsToToolBarManager(actions->helpActions()->actions(), tr("Help"), m_manager);
+
+    // Filter out the device profile preview actions which have int data().
+    ActionList previewActions = actions->styleActions()->actions();
+    ActionList::iterator it = previewActions.begin();
+    for ( ; (*it)->isSeparator() || (*it)->data().type() == QVariant::Int; ++it) ;
+    previewActions.erase(previewActions.begin(), it);
+    addActionsToToolBarManager(previewActions, tr("Style"), m_manager);
+
+    const QString dockTitle = tr("Dock views");
+    foreach (QDesignerToolWindow *tw, toolWindows) {
+        if (QAction *action = tw->action())
+            m_manager->addAction(action, dockTitle);
+    }
+
+    QString category(tr("File"));
+    foreach(QAction *action, actions->fileActions()->actions())
+        m_manager->addAction(action, category);
+
+    category = tr("Edit");
+    foreach(QAction *action, actions->editActions()->actions())
+        m_manager->addAction(action, category);
+
+    category = tr("Tools");
+    foreach(QAction *action, actions->toolActions()->actions())
+        m_manager->addAction(action, category);
+
+    category = tr("Form");
+    foreach(QAction *action, actions->formActions()->actions())
+        m_manager->addAction(action, category);
+
+    m_manager->addAction(m_configureAction, tr("Toolbars"));
+    updateToolBarMenu();
+}
+
+// sort function for sorting tool bars alphabetically by title [non-static since called from template]
+
+bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2)
+{
+    return t1->windowTitle() < t2->windowTitle();
+}
+
+void ToolBarManager::updateToolBarMenu()
+{
+    // Sort tool bars alphabetically by title
+    qStableSort(m_toolbars.begin(), m_toolbars.end(), toolBarTitleLessThan);
+    // add to menu
+    m_toolBarMenu->clear();
+    foreach (QToolBar *tb,  m_toolbars)
+        m_toolBarMenu->addAction(tb->toggleViewAction());
+    m_toolBarMenu->addAction(m_configureAction);
+}
+
+void ToolBarManager::configureToolBars()
+{
+    QtToolBarDialog dlg(m_parent);
+    dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
+    dlg.setToolBarManager(m_manager);
+    dlg.exec();
+    updateToolBarMenu();
+}
+
+QByteArray ToolBarManager::saveState(int version) const
+{
+    return m_manager->saveState(version);
+}
+
+bool ToolBarManager::restoreState(const QByteArray &state, int version)
+{
+    return m_manager->restoreState(state, version);
+}
+
+// ---------- DockedMainWindow
+
+DockedMainWindow::DockedMainWindow(QDesignerWorkbench *wb,
+                                   QMenu *toolBarMenu,
+                                   const QList<QDesignerToolWindow*> &toolWindows) :
+    m_toolBarManager(0)
+{
+    setObjectName(QLatin1String("MDIWindow"));
+    setWindowTitle(mainWindowTitle());
+
+    const QList<QToolBar *> toolbars = createToolBars(wb->actionManager(), false);
+    foreach (QToolBar *tb, toolbars)
+        addToolBar(tb);
+    DockedMdiArea *dma = new DockedMdiArea(wb->actionManager()->uiExtension());
+    connect(dma, SIGNAL(fileDropped(QString)),
+            this, SIGNAL(fileDropped(QString)));
+    connect(dma, SIGNAL(subWindowActivated(QMdiSubWindow*)),
+            this, SLOT(slotSubWindowActivated(QMdiSubWindow*)));
+    setCentralWidget(dma);
+
+    QStatusBar *sb = statusBar();
+    Q_UNUSED(sb)
+
+    m_toolBarManager = new ToolBarManager(this, this, toolBarMenu, wb->actionManager(), toolbars, toolWindows);
+}
+
+QMdiArea *DockedMainWindow::mdiArea() const
+{
+    return static_cast<QMdiArea *>(centralWidget());
+}
+
+void DockedMainWindow::slotSubWindowActivated(QMdiSubWindow* subWindow)
+{
+    if (subWindow) {
+        QWidget *widget = subWindow->widget();
+        if (QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow*>(widget)) {
+            emit formWindowActivated(fw);
+            mdiArea()->setActiveSubWindow(subWindow);
+        }
+    }
+}
+
+// Create a MDI subwindow for the form.
+QMdiSubWindow *DockedMainWindow::createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut)
+{
+    QMdiSubWindow *rc = mdiArea()->addSubWindow(fw, f);
+    // Make action shortcuts respond only if focused to avoid conflicts with
+    // designer menu actions
+    if (designerCloseActionShortCut == QKeySequence(QKeySequence::Close)) {
+        const ActionList systemMenuActions = rc->systemMenu()->actions();
+        if (!systemMenuActions.empty()) {
+            const ActionList::const_iterator cend = systemMenuActions.constEnd();
+            for (ActionList::const_iterator it = systemMenuActions.constBegin(); it != cend; ++it) {
+                if ( (*it)->shortcut() == designerCloseActionShortCut) {
+                    (*it)->setShortcutContext(Qt::WidgetShortcut);
+                    break;
+                }
+            }
+        }
+    }
+    return rc;
+}
+
+DockedMainWindow::DockWidgetList DockedMainWindow::addToolWindows(const DesignerToolWindowList &tls)
+{
+    DockWidgetList rc;
+    foreach (QDesignerToolWindow *tw, tls) {
+        QDockWidget *dockWidget = new QDockWidget;
+        dockWidget->setObjectName(tw->objectName() + QLatin1String("_dock"));
+        dockWidget->setWindowTitle(tw->windowTitle());
+        addDockWidget(tw->dockWidgetAreaHint(), dockWidget);
+        dockWidget->setWidget(tw);
+        rc.push_back(dockWidget);
+    }
+    return rc;
+}
+
+// Settings consist of MainWindow state and tool bar manager state
+void DockedMainWindow::restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea)
+{
+    const int version = settingsVersion();
+    m_toolBarManager->restoreState(s.toolBarsState(DockedMode), version);
+
+    // If there are no old geometry settings, show the window maximized
+    s.restoreGeometry(this, QRect(desktopArea.topLeft(), QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)));
+
+    const QByteArray mainWindowState = s.mainWindowState(DockedMode);
+    const bool restored = !mainWindowState.isEmpty() && restoreState(mainWindowState, version);
+    if (!restored) {
+        // Default: Tabify less relevant windows bottom/right.
+        tabifyDockWidget(dws.at(QDesignerToolWindow::SignalSlotEditor),
+                         dws.at(QDesignerToolWindow::ActionEditor));
+        tabifyDockWidget(dws.at(QDesignerToolWindow::ActionEditor),
+                         dws.at(QDesignerToolWindow::ResourceEditor));
+    }
+}
+
+void DockedMainWindow::saveSettings(QDesignerSettings &s) const
+{
+    const int version = settingsVersion();
+    s.setToolBarsState(DockedMode, m_toolBarManager->saveState(version));
+    s.saveGeometryFor(this);
+    s.setMainWindowState(DockedMode, saveState(version));
+}
+
+QT_END_NAMESPACE
+#include <moc_mainwindow.h>
diff --git a/src/designer/designer/mainwindow.h b/src/designer/designer/mainwindow.h
new file mode 100644 (file)
index 0000000..105ddcc
--- /dev/null
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtGui/QMainWindow>
+#include <QtCore/QList>
+#include <QtGui/QMdiArea>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerActions;
+class QDesignerWorkbench;
+class QDesignerToolWindow;
+class QDesignerFormWindow;
+class QDesignerSettings;
+
+class QtToolBarManager;
+class QToolBar;
+class QMdiArea;
+class QMenu;
+class QByteArray;
+class QMimeData;
+
+/* A main window that has a configureable policy on handling close events. If
+ * enabled, it can forward the close event to external handlers.
+ * Base class for windows that can switch roles between tool windows
+ * and main windows. */
+
+class MainWindowBase: public QMainWindow
+{
+    Q_DISABLE_COPY(MainWindowBase)
+    Q_OBJECT
+protected:
+    explicit MainWindowBase(QWidget *parent = 0, Qt::WindowFlags flags = Qt::Window);
+
+public:
+    enum CloseEventPolicy {
+        /* Always accept close events */
+        AcceptCloseEvents,
+        /* Emit a signal with the event, have it handled elsewhere */
+        EmitCloseEventSignal };
+
+    CloseEventPolicy closeEventPolicy() const { return m_policy; }
+    void setCloseEventPolicy(CloseEventPolicy pol) { m_policy = pol; }
+
+    static QList<QToolBar *> createToolBars(const QDesignerActions *actions, bool singleToolBar);
+    static QString mainWindowTitle();
+
+    // Use the minor Qt version as settings versions to avoid conflicts
+    static int settingsVersion();
+
+signals:
+    void closeEventReceived(QCloseEvent *e);
+
+protected:
+    virtual void closeEvent(QCloseEvent *e);
+private:
+    CloseEventPolicy m_policy;
+};
+
+/* An MdiArea that listens for desktop file manager file drop events and emits
+ * a signal to open a dropped file. */
+class DockedMdiArea : public QMdiArea
+{
+    Q_DISABLE_COPY(DockedMdiArea)
+    Q_OBJECT
+public:
+    explicit DockedMdiArea(const QString &extension, QWidget *parent = 0);
+
+signals:
+    void fileDropped(const QString &);
+
+protected:
+    bool event (QEvent *event);
+
+private:
+    QStringList uiFiles(const QMimeData *d) const;
+
+    const QString m_extension;
+};
+
+// Convenience class that manages a QtToolBarManager and an action to trigger
+// it on a mainwindow.
+class ToolBarManager : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(ToolBarManager)
+public:
+    explicit ToolBarManager(QMainWindow *configureableMainWindow,
+                            QWidget *parent,
+                            QMenu *toolBarMenu,
+                            const QDesignerActions *actions,
+                            const QList<QToolBar *> &toolbars,
+                            const QList<QDesignerToolWindow*> &toolWindows);
+
+    QByteArray saveState(int version = 0) const;
+    bool restoreState(const QByteArray &state, int version = 0);
+
+private slots:
+    void configureToolBars();
+    void updateToolBarMenu();
+
+private:
+    QMainWindow *m_configureableMainWindow;
+    QWidget *m_parent;
+    QMenu *m_toolBarMenu;
+    QtToolBarManager *m_manager;
+    QAction *m_configureAction;
+    QList<QToolBar *> m_toolbars;
+};
+
+/* Main window to be used for docked mode */
+class DockedMainWindow : public MainWindowBase {
+    Q_OBJECT
+    Q_DISABLE_COPY(DockedMainWindow)
+public:
+    typedef QList<QDesignerToolWindow*> DesignerToolWindowList;
+    typedef QList<QDockWidget *> DockWidgetList;
+
+    explicit DockedMainWindow(QDesignerWorkbench *wb,
+                              QMenu *toolBarMenu,
+                              const DesignerToolWindowList &toolWindows);
+
+    // Create a MDI subwindow for the form.
+    QMdiSubWindow *createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut);
+
+    QMdiArea *mdiArea() const;
+
+    DockWidgetList addToolWindows(const DesignerToolWindowList &toolWindows);
+
+    void restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea);
+    void saveSettings(QDesignerSettings &) const;
+
+signals:
+    void fileDropped(const QString &);
+    void formWindowActivated(QDesignerFormWindow *);
+
+private slots:
+    void slotSubWindowActivated(QMdiSubWindow*);
+
+private:
+    ToolBarManager *m_toolBarManager;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/src/designer/designer/newform.cpp b/src/designer/designer/newform.cpp
new file mode 100644 (file)
index 0000000..aef992a
--- /dev/null
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "newform.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_settings.h"
+
+#include <newformwidget_p.h>
+
+#include <QtDesigner/abstractformeditor.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QTemporaryFile>
+
+#include <QtGui/QApplication>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QMenu>
+#include <QtGui/QCheckBox>
+#include <QtGui/QFrame>
+#include <QtGui/QMessageBox>
+
+QT_BEGIN_NAMESPACE
+
+NewForm::NewForm(QDesignerWorkbench *workbench, QWidget *parentWidget, const QString &fileName)
+    : QDialog(parentWidget,
+#ifdef Q_WS_MAC
+            Qt::Tool |
+#endif
+            Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
+      m_fileName(fileName),
+      m_newFormWidget(QDesignerNewFormWidgetInterface::createNewFormWidget(workbench->core())),
+      m_workbench(workbench),
+      m_chkShowOnStartup(new QCheckBox(tr("Show this Dialog on Startup"))),
+      m_createButton(new QPushButton(QApplication::translate("NewForm", "C&reate", 0, QApplication::UnicodeUTF8))),
+      m_recentButton(new QPushButton(QApplication::translate("NewForm", "Recent", 0,  QApplication::UnicodeUTF8))),
+      m_buttonBox(0)
+{
+    setWindowTitle(tr("New Form"));
+    QDesignerSettings settings(m_workbench->core());
+
+    QVBoxLayout *vBoxLayout = new QVBoxLayout;
+
+    connect(m_newFormWidget, SIGNAL(templateActivated()), this, SLOT(slotTemplateActivated()));
+    connect(m_newFormWidget, SIGNAL(currentTemplateChanged(bool)), this, SLOT(slotCurrentTemplateChanged(bool)));
+    vBoxLayout->addWidget(m_newFormWidget);
+
+    QFrame *horizontalLine = new QFrame;
+    horizontalLine->setFrameShape(QFrame::HLine);
+    horizontalLine->setFrameShadow(QFrame::Sunken);
+    vBoxLayout->addWidget(horizontalLine);
+
+    m_chkShowOnStartup->setChecked(settings.showNewFormOnStartup());
+    vBoxLayout->addWidget(m_chkShowOnStartup);
+
+    m_buttonBox = createButtonBox();
+    vBoxLayout->addWidget(m_buttonBox);
+    setLayout(vBoxLayout);
+    
+    resize(500, 400);
+    slotCurrentTemplateChanged(m_newFormWidget->hasCurrentTemplate());
+}
+
+QDialogButtonBox *NewForm::createButtonBox()
+{
+    // Dialog buttons with 'recent files'
+    QDialogButtonBox *buttonBox = new QDialogButtonBox;
+    buttonBox->addButton(QApplication::translate("NewForm", "&Close", 0,
+                                        QApplication::UnicodeUTF8), QDialogButtonBox::RejectRole);
+    buttonBox->addButton(m_createButton, QDialogButtonBox::AcceptRole);
+    buttonBox->addButton(QApplication::translate("NewForm", "&Open...", 0,
+                                    QApplication::UnicodeUTF8), QDialogButtonBox::ActionRole);
+    buttonBox->addButton(m_recentButton, QDialogButtonBox::ActionRole);
+    QDesignerActions *da = m_workbench->actionManager();
+    QMenu *recentFilesMenu = new QMenu(tr("&Recent Forms"), m_recentButton);
+    // Pop the "Recent Files" stuff in here.
+    const QList<QAction *> recentActions = da->recentFilesActions()->actions();
+    if (!recentActions.empty()) {
+        const QList<QAction *>::const_iterator acend = recentActions.constEnd();
+        for (QList<QAction *>::const_iterator it = recentActions.constBegin(); it != acend; ++it) {
+            recentFilesMenu->addAction(*it);
+            connect(*it, SIGNAL(triggered()), this, SLOT(recentFileChosen()));
+        }
+    }
+    m_recentButton->setMenu(recentFilesMenu);
+    connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonBoxClicked(QAbstractButton*)));
+    return buttonBox;
+}
+
+NewForm::~NewForm()
+{
+    QDesignerSettings settings (m_workbench->core());
+    settings.setShowNewFormOnStartup(m_chkShowOnStartup->isChecked());
+}
+
+void NewForm::recentFileChosen()
+{
+    QAction *action = qobject_cast<QAction *>(sender());
+    if (!action)
+        return;
+    if (action->objectName() == QLatin1String("__qt_action_clear_menu_"))
+        return;
+    close();
+}
+
+void NewForm::slotCurrentTemplateChanged(bool templateSelected)
+{
+    if (templateSelected) {
+        m_createButton->setEnabled(true);
+        m_createButton->setDefault(true);
+    } else {
+        m_createButton->setEnabled(false);
+    }
+}
+
+void NewForm::slotTemplateActivated()
+{
+    m_createButton->animateClick(0);
+}
+
+void NewForm::slotButtonBoxClicked(QAbstractButton *btn)
+{
+    switch (m_buttonBox->buttonRole(btn)) {
+    case QDialogButtonBox::RejectRole:
+        reject();
+        break;
+    case QDialogButtonBox::ActionRole:
+        if (btn != m_recentButton) {
+            m_fileName.clear();
+            if (m_workbench->actionManager()->openForm(this))
+                accept();
+        }
+        break;
+    case QDialogButtonBox::AcceptRole: {
+        QString errorMessage;
+        if (openTemplate(&errorMessage)) {
+            accept();
+        }  else {
+            QMessageBox::warning(this, tr("Read error"), errorMessage);
+        }
+    }
+        break;
+    default:
+        break;
+    }
+}
+
+bool NewForm::openTemplate(QString *ptrToErrorMessage)
+{
+    const QString contents = m_newFormWidget->currentTemplate(ptrToErrorMessage);
+    if (contents.isEmpty())
+        return false;
+    // Write to temporary file and open
+    QString tempPattern = QDir::tempPath();
+    if (!tempPattern.endsWith(QDir::separator())) // platform-dependant
+        tempPattern += QDir::separator();
+    tempPattern += QLatin1String("XXXXXX.ui");
+    QTemporaryFile tempFormFile(tempPattern);
+
+    tempFormFile.setAutoRemove(true);
+    if (!tempFormFile.open()) {
+        *ptrToErrorMessage = tr("A temporary form file could not be created in %1.").arg(QDir::tempPath());
+        return false;
+    }
+    const QString tempFormFileName = tempFormFile.fileName();
+    tempFormFile.write(contents.toUtf8());
+    if (!tempFormFile.flush())  {
+        *ptrToErrorMessage = tr("The temporary form file %1 could not be written.").arg(tempFormFileName);
+        return false;
+    }
+    tempFormFile.close();
+    return m_workbench->openTemplate(tempFormFileName, m_fileName, ptrToErrorMessage);
+}
+
+QImage NewForm::grabForm(QDesignerFormEditorInterface *core,
+                         QIODevice &file,
+                         const QString &workingDir,
+                         const qdesigner_internal::DeviceProfile &dp)
+{
+    return qdesigner_internal::NewFormWidget::grabForm(core, file, workingDir, dp);
+}
+
+QT_END_NAMESPACE
+#include <moc_newform.h>
diff --git a/src/designer/designer/newform.h b/src/designer/designer/newform.h
new file mode 100644 (file)
index 0000000..f0508d7
--- /dev/null
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NEWFORM_H
+#define NEWFORM_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+    class DeviceProfile;
+}
+
+class QDesignerFormEditorInterface;
+class QDesignerNewFormWidgetInterface;
+class QDesignerWorkbench;
+
+class QCheckBox;
+class QAbstractButton;
+class QPushButton;
+class QDialogButtonBox;
+class QImage;
+class QIODevice;
+
+class NewForm: public QDialog
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(NewForm)
+
+public:
+    NewForm(QDesignerWorkbench *workbench,
+            QWidget *parentWidget,
+            // Use that file name instead of a temporary one
+            const QString &fileName = QString());
+
+    virtual ~NewForm();
+
+    // Convenience for implementing file dialogs with preview
+    static QImage grabForm(QDesignerFormEditorInterface *core,
+                           QIODevice &file,
+                           const QString &workingDir,
+                           const qdesigner_internal::DeviceProfile &dp);
+
+private slots:
+    void slotButtonBoxClicked(QAbstractButton *btn);
+    void recentFileChosen();
+    void slotCurrentTemplateChanged(bool templateSelected);
+    void slotTemplateActivated();
+
+private:
+    QDialogButtonBox *createButtonBox();
+    bool openTemplate(QString *ptrToErrorMessage);
+
+    QString m_fileName;
+    QDesignerNewFormWidgetInterface *m_newFormWidget;
+    QDesignerWorkbench *m_workbench;
+    QCheckBox *m_chkShowOnStartup;
+    QPushButton *m_createButton;
+    QPushButton *m_recentButton;
+    QDialogButtonBox *m_buttonBox;
+};
+
+QT_END_NAMESPACE
+
+#endif // NEWFORM_H
diff --git a/src/designer/designer/preferencesdialog.cpp b/src/designer/designer/preferencesdialog.cpp
new file mode 100644 (file)
index 0000000..8c93daa
--- /dev/null
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "preferencesdialog.h"
+#include "ui_preferencesdialog.h"
+#include "qdesigner_appearanceoptions.h"
+
+#include <QtDesigner/abstractoptionspage_p.h>
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtGui/QFileDialog>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+PreferencesDialog::PreferencesDialog(QDesignerFormEditorInterface *core, QWidget *parentWidget) :
+    QDialog(parentWidget),
+    m_ui(new Ui::PreferencesDialog()),
+    m_core(core)
+{
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+    m_ui->setupUi(this);
+
+    m_optionsPages = core->optionsPages();
+
+    m_ui->m_optionTabWidget->clear();
+    foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages) {
+        QWidget *page = optionsPage->createPage(this);
+        m_ui->m_optionTabWidget->addTab(page, optionsPage->name());
+        if (QDesignerAppearanceOptionsWidget *appearanceWidget = qobject_cast<QDesignerAppearanceOptionsWidget *>(page))
+            connect(appearanceWidget, SIGNAL(uiModeChanged(bool)), this, SLOT(slotUiModeChanged(bool)));
+    }
+
+    connect(m_ui->m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(slotRejected()));
+    connect(m_ui->m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(slotAccepted()));
+    connect(applyButton(), SIGNAL(clicked()), this, SLOT(slotApply()));
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+    delete m_ui;
+}
+
+QPushButton *PreferencesDialog::applyButton() const
+{
+    return m_ui->m_dialogButtonBox->button(QDialogButtonBox::Apply);
+}
+
+void PreferencesDialog::slotApply()
+{
+    foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages)
+        optionsPage->apply();
+}
+
+void PreferencesDialog::slotAccepted()
+{
+    slotApply();
+    closeOptionPages();
+    accept();
+}
+
+void PreferencesDialog::slotRejected()
+{
+    closeOptionPages();
+    reject();
+}
+
+void PreferencesDialog::slotUiModeChanged(bool modified)
+{
+    // Cannot "apply" a ui mode change (destroy the dialogs parent)
+    applyButton()->setEnabled(!modified);
+}
+
+void PreferencesDialog::closeOptionPages()
+{
+    foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages)
+        optionsPage->finish();
+}
+
+QT_END_NAMESPACE
+#include <moc_preferencesdialog.h>
diff --git a/src/designer/designer/preferencesdialog.h b/src/designer/designer/preferencesdialog.h
new file mode 100644 (file)
index 0000000..cd9c16b
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QPushButton;
+class QDesignerFormEditorInterface;
+class QDesignerOptionsPageInterface;
+
+namespace Ui {
+    class PreferencesDialog;
+}
+
+class PreferencesDialog: public QDialog
+{
+    Q_OBJECT
+public:
+    explicit PreferencesDialog(QDesignerFormEditorInterface *core, QWidget *parentWidget = 0);
+    ~PreferencesDialog();
+
+
+private slots:
+    void slotAccepted();
+    void slotRejected();
+    void slotApply();
+    void slotUiModeChanged(bool modified);
+
+private:
+    QPushButton *applyButton() const;
+    void closeOptionPages();
+
+    Ui::PreferencesDialog *m_ui;
+    QDesignerFormEditorInterface *m_core;
+    QList<QDesignerOptionsPageInterface*> m_optionsPages;
+};
+
+QT_END_NAMESPACE
+
+#endif // PREFERENCESDIALOG_H
diff --git a/src/designer/designer/preferencesdialog.ui b/src/designer/designer/preferencesdialog.ui
new file mode 100644 (file)
index 0000000..28d14bb
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesDialog</class>
+ <widget class="QDialog" name="PreferencesDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>474</width>
+    <height>304</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Preferences</string>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTabWidget" name="m_optionTabWidget">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab_2">
+      <attribute name="title">
+       <string notr="true">Tab 1</string>
+      </attribute>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="m_dialogButtonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Apply|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>m_dialogButtonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>PreferencesDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>m_dialogButtonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>PreferencesDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/designer/designer/qdesigner.cpp b/src/designer/designer/qdesigner.cpp
new file mode 100644 (file)
index 0000000..1d5b10d
--- /dev/null
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// designer
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_server.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_workbench.h"
+#include "mainwindow.h"
+
+#include <qdesigner_propertysheet_p.h>
+
+#include <QtGui/qevent.h>
+#include <QtGui/qevent.h>
+#include <QtGui/QMessageBox>
+#include <QtGui/QIcon>
+#include <QtGui/QErrorMessage>
+#include <QtCore/QMetaObject>
+#include <QtCore/QFile>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QLocale>
+#include <QtCore/QTimer>
+#include <QtCore/QTranslator>
+#include <QtCore/QFileInfo>
+#include <QtCore/qdebug.h>
+
+#include <QtDesigner/qdesigner_components.h>
+
+QT_BEGIN_NAMESPACE
+
+static const char *designerApplicationName = "Designer";
+static const char *designerWarningPrefix = "Designer: ";
+
+static void designerMessageHandler(QtMsgType type, const char *msg)
+{
+    // Only Designer warnings are displayed as box
+    QDesigner *designerApp = qDesigner;
+    if (type != QtWarningMsg || !designerApp || qstrncmp(designerWarningPrefix, msg, qstrlen(designerWarningPrefix))) {
+        qInstallMsgHandler(0);
+        qt_message_output(type, msg);
+        qInstallMsgHandler (designerMessageHandler);
+        return;
+    }
+    designerApp->showErrorMessage(msg);
+}
+
+QDesigner::QDesigner(int &argc, char **argv)
+    : QApplication(argc, argv),
+      m_server(0),
+      m_client(0),
+      m_workbench(0), m_suppressNewFormShow(false)
+{
+    setOrganizationName(QLatin1String("Trolltech"));
+    setApplicationName(QLatin1String(designerApplicationName));
+    QDesignerComponents::initializeResources();
+
+#ifndef Q_WS_MAC
+    setWindowIcon(QIcon(QLatin1String(":/trolltech/designer/images/designer.png")));
+#endif
+    initialize();
+}
+
+QDesigner::~QDesigner()
+{
+    if (m_workbench)
+        delete m_workbench;
+    if (m_server)
+        delete m_server;
+    if (m_client)
+        delete m_client;
+}
+
+void QDesigner::showErrorMessage(const char *message)
+{
+    // strip the prefix
+    const QString qMessage = QString::fromUtf8(message + qstrlen(designerWarningPrefix));
+    // If there is no main window yet, just store the message.
+    // The QErrorMessage would otherwise be hidden by the main window.
+    if (m_mainWindow) {
+        showErrorMessageBox(qMessage);
+    } else {
+        qInstallMsgHandler(0);
+        qt_message_output(QtWarningMsg, message); // just in case we crash
+        qInstallMsgHandler (designerMessageHandler);
+        m_initializationErrors += qMessage;
+        m_initializationErrors += QLatin1Char('\n');
+    }
+}
+
+void QDesigner::showErrorMessageBox(const QString &msg)
+{
+    // Manually suppress consecutive messages.
+    // This happens if for example sth is wrong with custom widget creation.
+    // The same warning will be displayed by Widget box D&D and form Drop
+    // while trying to create instance.
+    if (m_errorMessageDialog && m_lastErrorMessage == msg)
+        return;
+
+    if (!m_errorMessageDialog) {
+        m_lastErrorMessage.clear();
+        m_errorMessageDialog = new QErrorMessage(m_mainWindow);
+        const QString title = QCoreApplication::translate("QDesigner", "%1 - warning").arg(QLatin1String(designerApplicationName));
+        m_errorMessageDialog->setWindowTitle(title);
+        m_errorMessageDialog->setMinimumSize(QSize(600, 250));
+        m_errorMessageDialog->setWindowFlags(m_errorMessageDialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
+    }
+    m_errorMessageDialog->showMessage(msg);
+    m_lastErrorMessage = msg;
+}
+
+QDesignerWorkbench *QDesigner::workbench() const
+{
+    return m_workbench;
+}
+
+QDesignerServer *QDesigner::server() const
+{
+    return m_server;
+}
+
+bool QDesigner::parseCommandLineArgs(QStringList &fileNames, QString &resourceDir)
+{
+    const QStringList args = arguments();
+    const QStringList::const_iterator acend = args.constEnd();
+    QStringList::const_iterator it = args.constBegin();
+    for (++it; it != acend; ++it) {
+        const QString &argument = *it;
+        do {
+            // Arguments
+            if (!argument.startsWith(QLatin1Char('-'))) {
+                if (!fileNames.contains(argument))
+                    fileNames.append(argument);
+                break;
+            }
+            // Options
+            if (argument == QLatin1String("-server")) {
+                m_server = new QDesignerServer();
+                printf("%d\n", m_server->serverPort());
+                fflush(stdout);
+                break;
+            }
+            if (argument == QLatin1String("-client")) {
+                bool ok = true;
+                if (++it == acend) {
+                    qWarning("** WARNING The option -client requires an argument");
+                    return false;
+                }
+                const quint16 port = it->toUShort(&ok);
+                if (ok) {
+                    m_client = new QDesignerClient(port, this);
+                } else {
+                    qWarning("** WARNING Non-numeric argument specified for -client");
+                    return false;
+                }
+                break;
+            }
+            if (argument == QLatin1String("-resourcedir")) {
+                if (++it == acend) {
+                    qWarning("** WARNING The option -resourcedir requires an argument");
+                    return false;
+                }
+                resourceDir = QFile::decodeName(it->toLocal8Bit());
+                break;
+            }
+            if (argument == QLatin1String("-enableinternaldynamicproperties")) {
+                QDesignerPropertySheet::setInternalDynamicPropertiesEnabled(true);
+                break;
+            }
+            const QString msg = QString::fromUtf8("** WARNING Unknown option %1").arg(argument);
+            qWarning("%s", qPrintable(msg));
+        } while (false);
+    }
+    return true;
+}
+
+void QDesigner::initialize()
+{
+    // initialize the sub components
+    QStringList files;
+    QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+    parseCommandLineArgs(files, resourceDir);
+
+    QTranslator *translator = new QTranslator(this);
+    QTranslator *qtTranslator = new QTranslator(this);
+
+    const QString localSysName = QLocale::system().name();
+    QString  translatorFileName = QLatin1String("designer_");
+    translatorFileName += localSysName;
+    translator->load(translatorFileName, resourceDir);
+
+    translatorFileName = QLatin1String("qt_");
+    translatorFileName += localSysName;
+    qtTranslator->load(translatorFileName, resourceDir);
+    installTranslator(translator);
+    installTranslator(qtTranslator);
+
+    if (QLibraryInfo::licensedProducts() == QLatin1String("Console")) {
+        QMessageBox::information(0, tr("Qt Designer"),
+                tr("This application cannot be used for the Console edition of Qt"));
+        QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
+        return;
+    }
+
+    m_workbench = new QDesignerWorkbench();
+
+    emit initialized();
+    qInstallMsgHandler(designerMessageHandler); // Warn when loading faulty forms
+
+    m_suppressNewFormShow = m_workbench->readInBackup();
+
+    if (!files.empty()) {
+        const QStringList::const_iterator cend = files.constEnd();
+        for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+            // Ensure absolute paths for recent file list to be unique
+            QString fileName = *it;
+            const QFileInfo fi(fileName);
+            if (fi.exists() && fi.isRelative())
+                fileName = fi.absoluteFilePath();
+            m_workbench->readInForm(fileName);
+        }
+    }
+    if ( m_workbench->formWindowCount())
+        m_suppressNewFormShow = true;
+
+    // Show up error box with parent now if something went wrong
+    if (m_initializationErrors.isEmpty()) {
+        if (!m_suppressNewFormShow && QDesignerSettings(m_workbench->core()).showNewFormOnStartup())
+            QTimer::singleShot(100, this, SLOT(callCreateForm())); // won't show anything if suppressed
+    } else {
+        showErrorMessageBox(m_initializationErrors);
+        m_initializationErrors.clear();
+    }
+}
+
+bool QDesigner::event(QEvent *ev)
+{
+    bool eaten;
+    switch (ev->type()) {
+    case QEvent::FileOpen:
+        // Set it true first since, if it's a Qt 3 form, the messagebox from convert will fire the timer.
+        m_suppressNewFormShow = true;
+        if (!m_workbench->readInForm(static_cast<QFileOpenEvent *>(ev)->file()))
+            m_suppressNewFormShow = false;
+        eaten = true;
+        break;
+    case QEvent::Close: {
+        QCloseEvent *closeEvent = static_cast<QCloseEvent *>(ev);
+        closeEvent->setAccepted(m_workbench->handleClose());
+        if (closeEvent->isAccepted()) {
+            // We're going down, make sure that we don't get our settings saved twice.
+            if (m_mainWindow)
+                m_mainWindow->setCloseEventPolicy(MainWindowBase::AcceptCloseEvents);
+            eaten = QApplication::event(ev);
+        }
+        eaten = true;
+        break;
+    }
+    default:
+        eaten = QApplication::event(ev);
+        break;
+    }
+    return eaten;
+}
+
+void QDesigner::setMainWindow(MainWindowBase *tw)
+{
+    m_mainWindow = tw;
+}
+
+MainWindowBase *QDesigner::mainWindow() const
+{
+    return m_mainWindow;
+}
+
+void QDesigner::callCreateForm()
+{
+    if (!m_suppressNewFormShow)
+        m_workbench->actionManager()->createForm();
+}
+
+QT_END_NAMESPACE
+#include <moc_qdesigner.h>
diff --git a/src/designer/designer/qdesigner.h b/src/designer/designer/qdesigner.h
new file mode 100644 (file)
index 0000000..37bf872
--- /dev/null
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_H
+#define QDESIGNER_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+#define qDesigner \
+    (static_cast<QDesigner*>(QCoreApplication::instance()))
+
+class QDesignerWorkbench;
+class QDesignerToolWindow;
+class MainWindowBase;
+class QDesignerServer;
+class QDesignerClient;
+class QErrorMessage;
+
+class QDesigner: public QApplication
+{
+    Q_OBJECT
+public:
+    QDesigner(int &argc, char **argv);
+    virtual ~QDesigner();
+
+    QDesignerWorkbench *workbench() const;
+    QDesignerServer *server() const;
+    MainWindowBase *mainWindow() const;
+    void setMainWindow(MainWindowBase *tw);
+
+protected:
+    bool event(QEvent *ev);
+
+signals:
+    void initialized();
+
+public slots:
+    void showErrorMessage(const char *message);
+
+private slots:
+    void initialize();
+    void callCreateForm();
+
+private:
+    bool parseCommandLineArgs(QStringList &fileNames, QString &resourceDir);
+    void showErrorMessageBox(const QString &);
+
+    QDesignerServer *m_server;
+    QDesignerClient *m_client;
+    QDesignerWorkbench *m_workbench;
+    QPointer<MainWindowBase> m_mainWindow;
+    QPointer<QErrorMessage> m_errorMessageDialog;
+
+    QString m_initializationErrors;
+    QString m_lastErrorMessage;
+    bool m_suppressNewFormShow;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_H
diff --git a/src/designer/designer/qdesigner_actions.cpp b/src/designer/designer/qdesigner_actions.cpp
new file mode 100644 (file)
index 0000000..c1dc4a5
--- /dev/null
@@ -0,0 +1,1438 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_actions.h"
+#include "designer_enums.h"
+#include "qdesigner.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_formwindow.h"
+#include "newform.h"
+#include "versiondialog.h"
+#include "saveformastemplate.h"
+#include "qdesigner_toolwindow.h"
+#include "preferencesdialog.h"
+#include "appfontdialog.h"
+
+#include <pluginmanager_p.h>
+#include <qdesigner_formbuilder_p.h>
+#include <qdesigner_utils_p.h>
+#include <iconloader_p.h>
+#include <qsimpleresource_p.h>
+#include <previewmanager_p.h>
+#include <codedialog_p.h>
+#include <qdesigner_formwindowmanager_p.h>
+#include "qdesigner_integration_p.h"
+
+// sdk
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractlanguage.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/abstractformwindowcursor.h>
+#include <QtDesigner/abstractformeditorplugin.h>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtDesigner/shared_settings_p.h>
+#include <QtDesigner/formwindowbase_p.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QStyleFactory>
+#include <QtGui/qevent.h>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QIcon>
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QPrintDialog>
+#include <QtGui/QPainter>
+#include <QtGui/QTransform>
+#include <QtGui/QCursor>
+#include <QtCore/qsize.h>
+
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QBuffer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/qdebug.h>
+#include <QtCore/QTimer>
+#include <QtCore/QMetaObject>
+#include <QtCore/QFileInfo>
+#include <QtGui/QStatusBar>
+#include <QtGui/QDesktopWidget>
+#include <QtXml/qdom.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+const char *QDesignerActions::defaultToolbarPropertyName = "__qt_defaultToolBarAction";
+
+//#ifdef Q_WS_MAC
+#  define NONMODAL_PREVIEW
+//#endif
+
+static QAction *createSeparator(QObject *parent) {
+    QAction * rc = new QAction(parent);
+    rc->setSeparator(true);
+    return rc;
+}
+
+static QActionGroup *createActionGroup(QObject *parent, bool exclusive = false) {
+    QActionGroup * rc = new QActionGroup(parent);
+    rc->setExclusive(exclusive);
+    return rc;
+}
+
+static inline QString savedMessage(const QString &fileName)
+{
+    return QDesignerActions::tr("Saved %1.").arg(fileName);
+}
+
+// Prompt for a file and make sure an extension is added
+// unless the user explicitly specifies another one.
+
+static QString getSaveFileNameWithExtension(QWidget *parent, const QString &title, QString dir, const QString &filter, const QString &extension)
+{
+    const QChar dot = QLatin1Char('.');
+
+    QString saveFile;
+    while (true) {
+        saveFile = QFileDialog::getSaveFileName(parent, title, dir, filter, 0, QFileDialog::DontConfirmOverwrite);
+        if (saveFile.isEmpty())
+            return saveFile;
+
+        const QFileInfo fInfo(saveFile);
+        if (fInfo.suffix().isEmpty() && !fInfo.fileName().endsWith(dot)) {
+            saveFile += dot;
+            saveFile += extension;
+        }
+
+        const QFileInfo fi(saveFile);
+        if (!fi.exists())
+            break;
+
+        const QString prompt = QDesignerActions::tr("%1 already exists.\nDo you want to replace it?").arg(fi.fileName());
+        if (QMessageBox::warning(parent, title, prompt, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+            break;
+
+        dir = saveFile;
+    }
+    return saveFile;
+}
+
+QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
+    : QObject(workbench),
+      m_workbench(workbench),
+      m_core(workbench->core()),
+      m_settings(workbench->core()),
+      m_backupTimer(new QTimer(this)),
+      m_fileActions(createActionGroup(this)),
+      m_recentFilesActions(createActionGroup(this)),
+      m_editActions(createActionGroup(this)),
+      m_formActions(createActionGroup(this)),
+      m_settingsActions(createActionGroup(this)),
+      m_windowActions(createActionGroup(this)),
+      m_toolActions(createActionGroup(this, true)),
+      m_helpActions(0),
+      m_styleActions(0),
+      m_editWidgetsAction(new QAction(tr("Edit Widgets"), this)),
+      m_newFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("filenew.png")), tr("&New..."), this)),
+      m_openFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("fileopen.png")), tr("&Open..."), this)),
+      m_saveFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("filesave.png")), tr("&Save"), this)),
+      m_saveFormAsAction(new QAction(tr("Save &As..."), this)),
+      m_saveAllFormsAction(new QAction(tr("Save A&ll"), this)),
+      m_saveFormAsTemplateAction(new QAction(tr("Save As &Template..."), this)),
+      m_closeFormAction(new QAction(tr("&Close"), this)),
+      m_savePreviewImageAction(new QAction(tr("Save &Image..."), this)),
+      m_printPreviewAction(new QAction(tr("&Print..."), this)),
+      m_quitAction(new QAction(tr("&Quit"), this)),
+      m_previewFormAction(0),
+      m_viewCodeAction(new QAction(tr("View &Code..."), this)),
+      m_minimizeAction(new QAction(tr("&Minimize"), this)),
+      m_bringAllToFrontSeparator(createSeparator(this)),
+      m_bringAllToFrontAction(new QAction(tr("Bring All to Front"), this)),
+      m_windowListSeparatorAction(createSeparator(this)),
+      m_preferencesAction(new QAction(tr("Preferences..."), this)),
+      m_appFontAction(new QAction(tr("Additional Fonts..."), this)),
+      m_appFontDialog(0),
+#ifndef QT_NO_PRINTER
+      m_printer(0),
+#endif
+      m_previewManager(0)
+{
+#ifdef Q_WS_X11
+    m_newFormAction->setIcon(QIcon::fromTheme("document-new", m_newFormAction->icon()));
+    m_openFormAction->setIcon(QIcon::fromTheme("document-open", m_openFormAction->icon()));
+    m_saveFormAction->setIcon(QIcon::fromTheme("document-save", m_saveFormAction->icon()));
+    m_saveFormAsAction->setIcon(QIcon::fromTheme("document-save-as", m_saveFormAsAction->icon()));
+    m_printPreviewAction->setIcon(QIcon::fromTheme("document-print", m_printPreviewAction->icon()));
+    m_closeFormAction->setIcon(QIcon::fromTheme("window-close", m_closeFormAction->icon()));
+    m_quitAction->setIcon(QIcon::fromTheme("application-exit", m_quitAction->icon()));
+#endif
+
+    Q_ASSERT(m_core != 0);
+    qdesigner_internal::QDesignerFormWindowManager *ifwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager *>(m_core->formWindowManager());
+    Q_ASSERT(ifwm);
+    m_previewManager = ifwm->previewManager();
+    m_previewFormAction = ifwm->actionDefaultPreview();
+    m_styleActions = ifwm->actionGroupPreviewInStyle();
+    connect(ifwm, SIGNAL(formWindowSettingsChanged(QDesignerFormWindowInterface*)),
+            this, SLOT(formWindowSettingsChanged(QDesignerFormWindowInterface*)));
+
+    m_editWidgetsAction->setObjectName(QLatin1String("__qt_edit_widgets_action"));
+    m_newFormAction->setObjectName(QLatin1String("__qt_new_form_action"));
+    m_openFormAction->setObjectName(QLatin1String("__qt_open_form_action"));
+    m_saveFormAction->setObjectName(QLatin1String("__qt_save_form_action"));
+    m_saveFormAsAction->setObjectName(QLatin1String("__qt_save_form_as_action"));
+    m_saveAllFormsAction->setObjectName(QLatin1String("__qt_save_all_forms_action"));
+    m_saveFormAsTemplateAction->setObjectName(QLatin1String("__qt_save_form_as_template_action"));
+    m_closeFormAction->setObjectName(QLatin1String("__qt_close_form_action"));
+    m_quitAction->setObjectName(QLatin1String("__qt_quit_action"));
+    m_previewFormAction->setObjectName(QLatin1String("__qt_preview_form_action"));
+    m_viewCodeAction->setObjectName(QLatin1String("__qt_preview_code_action"));
+    m_minimizeAction->setObjectName(QLatin1String("__qt_minimize_action"));
+    m_bringAllToFrontAction->setObjectName(QLatin1String("__qt_bring_all_to_front_action"));
+    m_preferencesAction->setObjectName(QLatin1String("__qt_preferences_action"));
+
+    m_helpActions = createHelpActions();
+
+    m_newFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    m_openFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    m_saveFormAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+    QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
+    Q_ASSERT(formWindowManager != 0);
+
+//
+// file actions
+//
+    m_newFormAction->setShortcut(QKeySequence::New);
+    connect(m_newFormAction, SIGNAL(triggered()), this, SLOT(createForm()));
+    m_fileActions->addAction(m_newFormAction);
+
+    m_openFormAction->setShortcut(QKeySequence::Open);
+    connect(m_openFormAction, SIGNAL(triggered()), this, SLOT(slotOpenForm()));
+    m_fileActions->addAction(m_openFormAction);
+
+    m_fileActions->addAction(createRecentFilesMenu());
+    m_fileActions->addAction(createSeparator(this));
+
+    m_saveFormAction->setShortcut(QKeySequence::Save);
+    connect(m_saveFormAction, SIGNAL(triggered()), this, SLOT(saveForm()));
+    m_fileActions->addAction(m_saveFormAction);
+
+    connect(m_saveFormAsAction, SIGNAL(triggered()), this, SLOT(saveFormAs()));
+    m_fileActions->addAction(m_saveFormAsAction);
+
+#ifdef Q_OS_MAC
+    m_saveAllFormsAction->setShortcut(tr("ALT+CTRL+S"));
+#else
+    m_saveAllFormsAction->setShortcut(tr("CTRL+SHIFT+S")); // Commonly "Save As" on Mac
+#endif
+    connect(m_saveAllFormsAction, SIGNAL(triggered()), this, SLOT(saveAllForms()));
+    m_fileActions->addAction(m_saveAllFormsAction);
+
+    connect(m_saveFormAsTemplateAction, SIGNAL(triggered()), this, SLOT(saveFormAsTemplate()));
+    m_fileActions->addAction(m_saveFormAsTemplateAction);
+
+    m_fileActions->addAction(createSeparator(this));
+
+    m_printPreviewAction->setShortcut(QKeySequence::Print);
+    connect(m_printPreviewAction,  SIGNAL(triggered()), this, SLOT(printPreviewImage()));
+    m_fileActions->addAction(m_printPreviewAction);
+    m_printPreviewAction->setObjectName(QLatin1String("__qt_print_action"));
+
+    connect(m_savePreviewImageAction,  SIGNAL(triggered()), this, SLOT(savePreviewImage()));
+    m_savePreviewImageAction->setObjectName(QLatin1String("__qt_saveimage_action"));
+    m_fileActions->addAction(m_savePreviewImageAction);
+    m_fileActions->addAction(createSeparator(this));
+
+    m_closeFormAction->setShortcut(QKeySequence::Close);
+    connect(m_closeFormAction, SIGNAL(triggered()), this, SLOT(closeForm()));
+    m_fileActions->addAction(m_closeFormAction);
+    updateCloseAction();
+
+    m_fileActions->addAction(createSeparator(this));
+
+    m_quitAction->setShortcuts(QKeySequence::Quit);
+    m_quitAction->setMenuRole(QAction::QuitRole);
+    connect(m_quitAction, SIGNAL(triggered()), this, SLOT(shutdown()));
+    m_fileActions->addAction(m_quitAction);
+
+//
+// edit actions
+//
+    QAction *undoAction = formWindowManager->actionUndo();
+    undoAction->setObjectName(QLatin1String("__qt_undo_action"));
+    undoAction->setShortcut(QKeySequence::Undo);
+    m_editActions->addAction(undoAction);
+
+    QAction *redoAction = formWindowManager->actionRedo();
+    redoAction->setObjectName(QLatin1String("__qt_redo_action"));
+    redoAction->setShortcut(QKeySequence::Redo);
+    m_editActions->addAction(redoAction);
+
+    m_editActions->addAction(createSeparator(this));
+
+    m_editActions->addAction(formWindowManager->actionCut());
+    m_editActions->addAction(formWindowManager->actionCopy());
+    m_editActions->addAction(formWindowManager->actionPaste());
+    m_editActions->addAction(formWindowManager->actionDelete());
+
+    m_editActions->addAction(formWindowManager->actionSelectAll());
+
+    m_editActions->addAction(createSeparator(this));
+
+    m_editActions->addAction(formWindowManager->actionLower());
+    m_editActions->addAction(formWindowManager->actionRaise());
+
+    formWindowManager->actionLower()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionRaise()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+//
+// edit mode actions
+//
+
+    m_editWidgetsAction->setCheckable(true);
+    QList<QKeySequence> shortcuts;
+    shortcuts.append(QKeySequence(Qt::Key_F3));
+#if QT_VERSION >= 0x040900 // "ESC" switching to edit mode: Activate once item delegates handle shortcut overrides for ESC.
+    shortcuts.append(QKeySequence(Qt::Key_Escape));
+#endif
+    m_editWidgetsAction->setShortcuts(shortcuts);
+    QIcon fallback(m_core->resourceLocation() + QLatin1String("/widgettool.png"));
+    m_editWidgetsAction->setIcon(QIcon::fromTheme("designer-edit-widget", fallback));
+    connect(m_editWidgetsAction, SIGNAL(triggered()), this, SLOT(editWidgetsSlot()));
+    m_editWidgetsAction->setChecked(true);
+    m_editWidgetsAction->setEnabled(false);
+    m_editWidgetsAction->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    m_toolActions->addAction(m_editWidgetsAction);
+
+    connect(formWindowManager, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+                this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+
+    QList<QObject*> builtinPlugins = QPluginLoader::staticInstances();
+    builtinPlugins += m_core->pluginManager()->instances();
+    foreach (QObject *plugin, builtinPlugins) {
+        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
+            if (QAction *action = formEditorPlugin->action()) {
+                m_toolActions->addAction(action);
+                action->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+                action->setCheckable(true);
+            }
+        }
+    }
+
+    connect(m_preferencesAction, SIGNAL(triggered()),  this, SLOT(showPreferencesDialog()));
+    m_preferencesAction->setMenuRole(QAction::PreferencesRole);
+    m_settingsActions->addAction(m_preferencesAction);
+
+    connect(m_appFontAction, SIGNAL(triggered()),  this, SLOT(showAppFontDialog()));
+    m_appFontAction->setMenuRole(QAction::PreferencesRole);
+    m_settingsActions->addAction(m_appFontAction);
+//
+// form actions
+//
+
+    m_formActions->addAction(formWindowManager->actionHorizontalLayout());
+    m_formActions->addAction(formWindowManager->actionVerticalLayout());
+    m_formActions->addAction(formWindowManager->actionSplitHorizontal());
+    m_formActions->addAction(formWindowManager->actionSplitVertical());
+    m_formActions->addAction(formWindowManager->actionGridLayout());
+    m_formActions->addAction(formWindowManager->actionFormLayout());
+    m_formActions->addAction(formWindowManager->actionBreakLayout());
+    m_formActions->addAction(formWindowManager->actionAdjustSize());
+    m_formActions->addAction(formWindowManager->actionSimplifyLayout());
+    m_formActions->addAction(createSeparator(this));
+
+    formWindowManager->actionHorizontalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionVerticalLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionSplitHorizontal()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionSplitVertical()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionGridLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionFormLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionBreakLayout()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+    formWindowManager->actionAdjustSize()->setProperty(QDesignerActions::defaultToolbarPropertyName, true);
+
+    m_previewFormAction->setShortcut(tr("CTRL+R"));
+    m_formActions->addAction(m_previewFormAction);
+    connect(m_previewManager, SIGNAL(firstPreviewOpened()), this, SLOT(updateCloseAction()));
+    connect(m_previewManager, SIGNAL(lastPreviewClosed()), this, SLOT(updateCloseAction()));
+
+    connect(m_viewCodeAction, SIGNAL(triggered()), this, SLOT(viewCode()));
+    // Preview code only in Cpp
+    if (qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core) == 0)
+        m_formActions->addAction(m_viewCodeAction);
+
+    m_formActions->addAction(createSeparator(this));
+
+    m_formActions->addAction(ifwm->actionShowFormWindowSettingsDialog());
+//
+// window actions
+//
+    m_minimizeAction->setEnabled(false);
+    m_minimizeAction->setCheckable(true);
+    m_minimizeAction->setShortcut(tr("CTRL+M"));
+    connect(m_minimizeAction, SIGNAL(triggered()), m_workbench, SLOT(toggleFormMinimizationState()));
+    m_windowActions->addAction(m_minimizeAction);
+
+    m_windowActions->addAction(m_bringAllToFrontSeparator);
+    connect(m_bringAllToFrontAction, SIGNAL(triggered()), m_workbench, SLOT(bringAllToFront()));
+    m_windowActions->addAction(m_bringAllToFrontAction);
+    m_windowActions->addAction(m_windowListSeparatorAction);
+
+    setWindowListSeparatorVisible(false);
+
+//
+// connections
+//
+    fixActionContext();
+    activeFormWindowChanged(core()->formWindowManager()->activeFormWindow());
+
+    m_backupTimer->start(180000); // 3min
+    connect(m_backupTimer, SIGNAL(timeout()), this, SLOT(backupForms()));
+
+    // Enable application font action
+    connect(formWindowManager, SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)), this, SLOT(formWindowCountChanged()));
+    connect(formWindowManager, SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)), this, SLOT(formWindowCountChanged()));
+    formWindowCountChanged();
+}
+
+QActionGroup *QDesignerActions::createHelpActions()
+{
+    QActionGroup *helpActions = createActionGroup(this);
+
+#ifndef QT_JAMBI_BUILD
+    QAction *mainHelpAction = new QAction(tr("Qt Designer &Help"), this);
+    mainHelpAction->setObjectName(QLatin1String("__qt_designer_help_action"));
+    connect(mainHelpAction, SIGNAL(triggered()), this, SLOT(showDesignerHelp()));
+    mainHelpAction->setShortcut(Qt::CTRL + Qt::Key_Question);
+    helpActions->addAction(mainHelpAction);
+
+    helpActions->addAction(createSeparator(this));
+    QAction *widgetHelp = new QAction(tr("Current Widget Help"), this);
+    widgetHelp->setObjectName(QLatin1String("__qt_current_widget_help_action"));
+    widgetHelp->setShortcut(Qt::Key_F1);
+    connect(widgetHelp, SIGNAL(triggered()), this, SLOT(showWidgetSpecificHelp()));
+    helpActions->addAction(widgetHelp);
+
+    helpActions->addAction(createSeparator(this));
+    QAction *whatsNewAction = new QAction(tr("What's New in Qt Designer?"), this);
+    whatsNewAction->setObjectName(QLatin1String("__qt_whats_new_in_qt_designer_action"));
+    connect(whatsNewAction, SIGNAL(triggered()), this, SLOT(showWhatsNew()));
+    helpActions->addAction(whatsNewAction);
+#endif
+
+    helpActions->addAction(createSeparator(this));
+    QAction *aboutPluginsAction = new QAction(tr("About Plugins"), this);
+    aboutPluginsAction->setObjectName(QLatin1String("__qt_about_plugins_action"));
+    aboutPluginsAction->setMenuRole(QAction::ApplicationSpecificRole);
+    connect(aboutPluginsAction, SIGNAL(triggered()), m_core->formWindowManager(), SLOT(aboutPlugins()));
+    helpActions->addAction(aboutPluginsAction);
+
+    QAction *aboutDesignerAction = new QAction(tr("About Qt Designer"), this);
+    aboutDesignerAction->setMenuRole(QAction::AboutRole);
+    aboutDesignerAction->setObjectName(QLatin1String("__qt_about_designer_action"));
+    connect(aboutDesignerAction, SIGNAL(triggered()), this, SLOT(aboutDesigner()));
+    helpActions->addAction(aboutDesignerAction);
+
+    QAction *aboutQtAction = new QAction(tr("About Qt"), this);
+    aboutQtAction->setMenuRole(QAction::AboutQtRole);
+    aboutQtAction->setObjectName(QLatin1String("__qt_about_qt_action"));
+    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+    helpActions->addAction(aboutQtAction);
+    return helpActions;
+}
+
+QDesignerActions::~QDesignerActions()
+{
+#ifndef QT_NO_PRINTER
+    delete m_printer;
+#endif
+}
+
+QString QDesignerActions::uiExtension() const
+{
+    QDesignerLanguageExtension *lang
+        = qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core);
+    if (lang)
+        return lang->uiExtension();
+    return QLatin1String("ui");
+}
+
+QAction *QDesignerActions::createRecentFilesMenu()
+{
+    QMenu *menu = new QMenu;
+    QAction *act;
+    // Need to insert this into the QAction.
+    for (int i = 0; i < MaxRecentFiles; ++i) {
+        act = new QAction(this);
+        act->setVisible(false);
+        connect(act, SIGNAL(triggered()), this, SLOT(openRecentForm()));
+        m_recentFilesActions->addAction(act);
+        menu->addAction(act);
+    }
+    updateRecentFileActions();
+    menu->addSeparator();
+    act = new QAction(QIcon::fromTheme("edit-clear"), tr("Clear &Menu"), this);
+    act->setObjectName(QLatin1String("__qt_action_clear_menu_"));
+    connect(act, SIGNAL(triggered()), this, SLOT(clearRecentFiles()));
+    m_recentFilesActions->addAction(act);
+    menu->addAction(act);
+
+    act = new QAction(QIcon::fromTheme("document-open-recent"), tr("&Recent Forms"), this);
+    act->setMenu(menu);
+    return act;
+}
+
+QActionGroup *QDesignerActions::toolActions() const
+{ return m_toolActions; }
+
+QDesignerWorkbench *QDesignerActions::workbench() const
+{ return m_workbench; }
+
+QDesignerFormEditorInterface *QDesignerActions::core() const
+{ return m_core; }
+
+QActionGroup *QDesignerActions::fileActions() const
+{ return m_fileActions; }
+
+QActionGroup *QDesignerActions::editActions() const
+{ return m_editActions; }
+
+QActionGroup *QDesignerActions::formActions() const
+{ return m_formActions; }
+
+QActionGroup *QDesignerActions::settingsActions() const
+{  return m_settingsActions; }
+
+QActionGroup *QDesignerActions::windowActions() const
+{ return m_windowActions; }
+
+QActionGroup *QDesignerActions::helpActions() const
+{ return m_helpActions; }
+
+QActionGroup *QDesignerActions::styleActions() const
+{ return m_styleActions; }
+
+QAction *QDesignerActions::previewFormAction() const
+{ return m_previewFormAction; }
+
+QAction *QDesignerActions::viewCodeAction() const
+{ return m_viewCodeAction; }
+
+
+void QDesignerActions::editWidgetsSlot()
+{
+    QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+    for (int i=0; i<formWindowManager->formWindowCount(); ++i) {
+        QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
+        formWindow->editWidgets();
+    }
+}
+
+void QDesignerActions::createForm()
+{
+    showNewFormDialog(QString());
+}
+
+void QDesignerActions::showNewFormDialog(const QString &fileName)
+{
+    closePreview();
+    NewForm *dlg = new NewForm(workbench(), workbench()->core()->topLevel(), fileName);
+
+    dlg->setAttribute(Qt::WA_DeleteOnClose);
+    dlg->setAttribute(Qt::WA_ShowModal);
+
+    dlg->setGeometry(fixDialogRect(dlg->rect()));
+    dlg->exec();
+}
+
+void QDesignerActions::slotOpenForm()
+{
+    openForm(core()->topLevel());
+}
+
+bool QDesignerActions::openForm(QWidget *parent)
+{
+    closePreview();
+    const QString extension = uiExtension();
+    const QStringList fileNames = QFileDialog::getOpenFileNames(parent, tr("Open Form"),
+        m_openDirectory, tr("Designer UI files (*.%1);;All Files (*)").arg(extension), 0, QFileDialog::DontUseSheet);
+
+    if (fileNames.isEmpty())
+        return false;
+
+    bool atLeastOne = false;
+    foreach (const QString &fileName, fileNames) {
+        if (readInForm(fileName) && !atLeastOne)
+            atLeastOne = true;
+    }
+
+    return atLeastOne;
+}
+
+bool QDesignerActions::saveFormAs(QDesignerFormWindowInterface *fw)
+{
+    const QString extension = uiExtension();
+
+    QString dir = fw->fileName();
+    if (dir.isEmpty()) {
+        do {
+            // Build untitled name
+            if (!m_saveDirectory.isEmpty()) {
+                dir = m_saveDirectory;
+                break;
+            }
+            if (!m_openDirectory.isEmpty()) {
+                dir = m_openDirectory;
+                break;
+            }
+            dir = QDir::current().absolutePath();
+        } while (false);
+        dir += QDir::separator();
+        dir += QLatin1String("untitled.");
+        dir += extension;
+    }
+
+    const  QString saveFile = getSaveFileNameWithExtension(fw, tr("Save Form As"), dir, tr("Designer UI files (*.%1);;All Files (*)").arg(extension), extension);
+    if (saveFile.isEmpty())
+        return false;
+
+    fw->setFileName(saveFile);
+    return writeOutForm(fw, saveFile);
+}
+
+void QDesignerActions::saveForm()
+{
+    if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+        if (saveForm(fw))
+            showStatusBarMessage(savedMessage(QFileInfo(fw->fileName()).fileName()));
+    }
+}
+
+void QDesignerActions::saveAllForms()
+{
+    QString fileNames;
+    QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+    if (const int totalWindows = formWindowManager->formWindowCount()) {
+        const QString separator = QLatin1String(", ");
+        for (int i = 0; i < totalWindows; ++i) {
+            QDesignerFormWindowInterface *fw = formWindowManager->formWindow(i);
+            if (fw && fw->isDirty()) {
+                formWindowManager->setActiveFormWindow(fw);
+                if (saveForm(fw)) {
+                    if (!fileNames.isEmpty())
+                        fileNames += separator;
+                    fileNames += QFileInfo(fw->fileName()).fileName();
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    if (!fileNames.isEmpty()) {
+        showStatusBarMessage(savedMessage(fileNames));
+    }
+}
+
+bool QDesignerActions::saveForm(QDesignerFormWindowInterface *fw)
+{
+    bool ret;
+    if (fw->fileName().isEmpty())
+        ret = saveFormAs(fw);
+    else
+        ret =  writeOutForm(fw, fw->fileName());
+    return ret;
+}
+
+void QDesignerActions::closeForm()
+{
+    if (m_previewManager->previewCount()) {
+        closePreview();
+        return;
+    }
+
+    if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow())
+        if (QWidget *parent = fw->parentWidget()) {
+            if (QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(parent->parentWidget())) {
+                mdiSubWindow->close();
+            } else {
+                parent->close();
+            }
+        }
+}
+
+void QDesignerActions::saveFormAs()
+{
+    if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+        if (saveFormAs(fw))
+            showStatusBarMessage(savedMessage(fw->fileName()));
+    }
+}
+
+void QDesignerActions::saveFormAsTemplate()
+{
+    if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+        SaveFormAsTemplate dlg(core(), fw, fw->window());
+        dlg.exec();
+    }
+}
+
+void QDesignerActions::notImplementedYet()
+{
+    QMessageBox::information(core()->topLevel(), tr("Designer"), tr("Feature not implemented yet!"));
+}
+
+void QDesignerActions::closePreview()
+{
+    m_previewManager->closeAllPreviews();
+}
+
+void  QDesignerActions::viewCode()
+{
+    QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+    if (!fw)
+        return;
+    QString errorMessage;
+    if (!qdesigner_internal::CodeDialog::showCodeDialog(fw, fw, &errorMessage))
+        QMessageBox::warning(fw, tr("Code generation failed"), errorMessage);
+}
+
+void QDesignerActions::fixActionContext()
+{
+    QList<QAction*> actions;
+    actions += m_fileActions->actions();
+    actions += m_editActions->actions();
+    actions += m_toolActions->actions();
+    actions += m_formActions->actions();
+    actions += m_windowActions->actions();
+    actions += m_helpActions->actions();
+
+    foreach (QAction *a, actions) {
+        a->setShortcutContext(Qt::ApplicationShortcut);
+    }
+}
+
+bool QDesignerActions::readInForm(const QString &fileName)
+{
+    QString fn = fileName;
+
+    // First make sure that we don't have this one open already.
+    QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+    const int totalWindows = formWindowManager->formWindowCount();
+    for (int i = 0; i < totalWindows; ++i) {
+        QDesignerFormWindowInterface *w = formWindowManager->formWindow(i);
+        if (w->fileName() == fn) {
+            w->raise();
+            formWindowManager->setActiveFormWindow(w);
+            addRecentFile(fn);
+            return true;
+        }
+    }
+
+    // Otherwise load it.
+    do {
+        QString errorMessage;
+        if (workbench()->openForm(fn, &errorMessage)) {
+            addRecentFile(fn);
+            m_openDirectory = QFileInfo(fn).absolutePath();
+            return true;
+        } else {
+            // prompt to reload
+            QMessageBox box(QMessageBox::Warning, tr("Read error"),
+                            tr("%1\nDo you want to update the file location or generate a new form?").arg(errorMessage),
+                            QMessageBox::Cancel, core()->topLevel());
+
+            QPushButton *updateButton = box.addButton(tr("&Update"), QMessageBox::ActionRole);
+            QPushButton *newButton    = box.addButton(tr("&New Form"), QMessageBox::ActionRole);
+            box.exec();
+            if (box.clickedButton() == box.button(QMessageBox::Cancel))
+                return false;
+
+            if (box.clickedButton() == updateButton) {
+                const QString extension = uiExtension();
+                fn = QFileDialog::getOpenFileName(core()->topLevel(),
+                                                  tr("Open Form"), m_openDirectory,
+                                                  tr("Designer UI files (*.%1);;All Files (*)").arg(extension), 0, QFileDialog::DontUseSheet);
+
+                if (fn.isEmpty())
+                    return false;
+            } else if (box.clickedButton() == newButton) {
+                // If the file does not exist, but its directory, is valid, open the template with the editor file name set to it.
+                // (called from command line).
+                QString newFormFileName;
+                const  QFileInfo fInfo(fn);
+                if (!fInfo.exists()) {
+                    // Normalize file name
+                    const QString directory = fInfo.absolutePath();
+                    if (QDir(directory).exists()) {
+                        newFormFileName = directory;
+                        newFormFileName  += QLatin1Char('/');
+                        newFormFileName  += fInfo.fileName();
+                    }
+                }
+                showNewFormDialog(newFormFileName);
+                return false;
+            }
+        }
+    } while (true);
+    return true;
+}
+
+static QString createBackup(const QString &fileName)
+{
+    const QString suffix = QLatin1String(".bak");
+    QString backupFile = fileName + suffix;
+    QFileInfo fi(backupFile);
+    int i = 0;
+    while (fi.exists()) {
+        backupFile = fileName + suffix + QString::number(++i);
+        fi.setFile(backupFile);
+    }
+
+    if (QFile::copy(fileName, backupFile))
+        return backupFile;
+    return QString();
+}
+
+static void removeBackup(const QString &backupFile)
+{
+    if (!backupFile.isEmpty())
+        QFile::remove(backupFile);
+}
+
+bool QDesignerActions::writeOutForm(QDesignerFormWindowInterface *fw, const QString &saveFile)
+{
+    Q_ASSERT(fw && !saveFile.isEmpty());
+
+    QString backupFile;
+    QFileInfo fi(saveFile);
+    if (fi.exists())
+        backupFile = createBackup(saveFile);
+
+    QString contents = fw->contents();
+    if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fw)) {
+        if (fwb->lineTerminatorMode() == qdesigner_internal::FormWindowBase::CRLFLineTerminator)
+            contents.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+    }
+    const QByteArray utf8Array = contents.toUtf8();
+    m_workbench->updateBackup(fw);
+
+    QFile f(saveFile);
+    while (!f.open(QFile::WriteOnly)) {
+        QMessageBox box(QMessageBox::Warning,
+                        tr("Save Form?"),
+                        tr("Could not open file"),
+                        QMessageBox::NoButton, fw);
+
+        box.setWindowModality(Qt::WindowModal);
+        box.setInformativeText(tr("The file %1 could not be opened."
+                               "\nReason: %2"
+                               "\nWould you like to retry or select a different file?")
+                                .arg(f.fileName()).arg(f.errorString()));
+        QPushButton *retryButton = box.addButton(QMessageBox::Retry);
+        retryButton->setDefault(true);
+        QPushButton *switchButton = box.addButton(tr("Select New File"), QMessageBox::AcceptRole);
+        QPushButton *cancelButton = box.addButton(QMessageBox::Cancel);
+        box.exec();
+
+        if (box.clickedButton() == cancelButton) {
+            removeBackup(backupFile);
+            return false;
+        } else if (box.clickedButton() == switchButton) {
+            QString extension = uiExtension();
+            const QString fileName = QFileDialog::getSaveFileName(fw, tr("Save Form As"),
+                                                                  QDir::current().absolutePath(),
+                                                                  QLatin1String("*.") + extension);
+            if (fileName.isEmpty()) {
+                removeBackup(backupFile);
+                return false;
+            }
+            if (f.fileName() != fileName) {
+                removeBackup(backupFile);
+                fi.setFile(fileName);
+                backupFile.clear();
+                if (fi.exists())
+                    backupFile = createBackup(fileName);
+            }
+            f.setFileName(fileName);
+            fw->setFileName(fileName);
+        }
+        // loop back around...
+    }
+    while (f.write(utf8Array, utf8Array.size()) != utf8Array.size()) {
+        QMessageBox box(QMessageBox::Warning, tr("Save Form?"),
+                        tr("Could not write file"),
+                        QMessageBox::Retry|QMessageBox::Cancel, fw);
+        box.setWindowModality(Qt::WindowModal);
+        box.setInformativeText(tr("It was not possible to write the entire file %1 to disk."
+                                "\nReason:%2\nWould you like to retry?")
+                                .arg(f.fileName()).arg(f.errorString()));
+        box.setDefaultButton(QMessageBox::Retry);
+        switch (box.exec()) {
+        case QMessageBox::Retry:
+            f.resize(0);
+            break;
+        default:
+            return false;
+        }
+    }
+    f.close();
+    removeBackup(backupFile);
+    addRecentFile(saveFile);
+    m_saveDirectory = QFileInfo(f).absolutePath();
+
+    fw->setDirty(false);
+    fw->parentWidget()->setWindowModified(false);
+    return true;
+}
+
+void QDesignerActions::shutdown()
+{
+    // Follow the idea from the Mac, i.e. send the Application a close event
+    // and if it's accepted, quit.
+    QCloseEvent ev;
+    QApplication::sendEvent(qDesigner, &ev);
+    if (ev.isAccepted())
+        qDesigner->quit();
+}
+
+void QDesignerActions::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+    const bool enable = formWindow != 0;
+    m_saveFormAction->setEnabled(enable);
+    m_saveFormAsAction->setEnabled(enable);
+    m_saveAllFormsAction->setEnabled(enable);
+    m_saveFormAsTemplateAction->setEnabled(enable);
+    m_closeFormAction->setEnabled(enable);
+    m_savePreviewImageAction->setEnabled(enable);
+    m_printPreviewAction->setEnabled(enable);
+
+    m_editWidgetsAction->setEnabled(enable);
+
+    m_previewFormAction->setEnabled(enable);
+    m_viewCodeAction->setEnabled(enable);
+    m_styleActions->setEnabled(enable);
+}
+
+void QDesignerActions::formWindowSettingsChanged(QDesignerFormWindowInterface *fw)
+{
+    if (QDesignerFormWindow *window = m_workbench->findFormWindow(fw))
+        window->updateChanged();
+}
+
+void QDesignerActions::updateRecentFileActions()
+{
+    QStringList files = m_settings.recentFilesList();
+    const int originalSize = files.size();
+    int numRecentFiles = qMin(files.size(), int(MaxRecentFiles));
+    const QList<QAction *> recentFilesActs = m_recentFilesActions->actions();
+
+    for (int i = 0; i < numRecentFiles; ++i) {
+        const QFileInfo fi(files[i]);
+        // If the file doesn't exist anymore, just remove it from the list so
+        // people don't get confused.
+        if (!fi.exists()) {
+            files.removeAt(i);
+            --i;
+            numRecentFiles = qMin(files.size(), int(MaxRecentFiles));
+            continue;
+        }
+        const QString text = fi.fileName();
+        recentFilesActs[i]->setText(text);
+        recentFilesActs[i]->setIconText(files[i]);
+        recentFilesActs[i]->setVisible(true);
+    }
+
+    for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
+        recentFilesActs[j]->setVisible(false);
+
+    // If there's been a change, right it back
+    if (originalSize != files.size())
+        m_settings.setRecentFilesList(files);
+}
+
+void QDesignerActions::openRecentForm()
+{
+    if (const QAction *action = qobject_cast<const QAction *>(sender())) {
+        if (!readInForm(action->iconText()))
+            updateRecentFileActions(); // File doesn't exist, remove it from settings
+    }
+}
+
+void QDesignerActions::clearRecentFiles()
+{
+    m_settings.setRecentFilesList(QStringList());
+    updateRecentFileActions();
+}
+
+QActionGroup *QDesignerActions::recentFilesActions() const
+{
+    return m_recentFilesActions;
+}
+
+void QDesignerActions::addRecentFile(const QString &fileName)
+{
+    QStringList files = m_settings.recentFilesList();
+    files.removeAll(fileName);
+    files.prepend(fileName);
+    while (files.size() > MaxRecentFiles)
+        files.removeLast();
+
+    m_settings.setRecentFilesList(files);
+    updateRecentFileActions();
+}
+
+QAction *QDesignerActions::openFormAction() const
+{
+    return  m_openFormAction;
+}
+
+QAction *QDesignerActions::closeFormAction() const
+{
+    return m_closeFormAction;
+}
+
+QAction *QDesignerActions::minimizeAction() const
+{
+    return m_minimizeAction;
+}
+
+void QDesignerActions::showDesignerHelp()
+{
+    QString url = AssistantClient::designerManualUrl();
+    url += QLatin1String("designer-manual.html");
+    showHelp(url);
+}
+
+void QDesignerActions::showWhatsNew()
+{
+    QString url = AssistantClient::qtReferenceManualUrl();
+    url += QLatin1String("qt4-designer.html");
+    showHelp(url);
+}
+
+void QDesignerActions::helpRequested(const QString &manual, const QString &document)
+{
+    QString url = AssistantClient::documentUrl(manual);
+    url += document;
+    showHelp(url);
+}
+
+void QDesignerActions::showHelp(const QString &url)
+{
+    QString errorMessage;
+    if (!m_assistantClient.showPage(url, &errorMessage))
+        QMessageBox::warning(core()->topLevel(), tr("Assistant"), errorMessage);
+}
+
+void QDesignerActions::aboutDesigner()
+{
+    VersionDialog mb(core()->topLevel());
+    mb.setWindowTitle(tr("About Qt Designer"));
+    if (mb.exec()) {
+        QMessageBox messageBox(QMessageBox::Information, QLatin1String("Easter Egg"),
+                               QLatin1String("Easter Egg"), QMessageBox::Ok, core()->topLevel());
+        messageBox.setInformativeText(QLatin1String("The Easter Egg has been removed."));
+        messageBox.exec();
+    }
+}
+
+QAction *QDesignerActions::editWidgets() const
+{
+    return m_editWidgetsAction;
+}
+
+void QDesignerActions::showWidgetSpecificHelp()
+{
+    QString helpId;
+    if (const qdesigner_internal::QDesignerIntegration *integration = qobject_cast<qdesigner_internal::QDesignerIntegration *>(core()->integration()))
+        helpId = integration->contextHelpId();
+
+    if (helpId.isEmpty()) {
+        showDesignerHelp();
+        return;
+    }
+
+    QString errorMessage;
+    const bool rc = m_assistantClient.activateIdentifier(helpId, &errorMessage);
+    if (!rc)
+        QMessageBox::warning(core()->topLevel(), tr("Assistant"), errorMessage);
+}
+
+void QDesignerActions::updateCloseAction()
+{
+    if (m_previewManager->previewCount()) {
+        m_closeFormAction->setText(tr("&Close Preview"));
+    } else {
+        m_closeFormAction->setText(tr("&Close"));
+    }
+}
+
+void QDesignerActions::backupForms()
+{
+    const int count = m_workbench->formWindowCount();
+    if (!count || !ensureBackupDirectories())
+        return;
+
+
+    QStringList tmpFiles;
+    QMap<QString, QString> backupMap;
+    QDir backupDir(m_backupPath);
+    const bool warningsEnabled = qdesigner_internal::QSimpleResource::setWarningsEnabled(false);
+    for (int i = 0; i < count; ++i) {
+        QDesignerFormWindow *fw = m_workbench->formWindow(i);
+        QDesignerFormWindowInterface *fwi = fw->editor();
+
+        QString formBackupName;
+        QTextStream(&formBackupName) << m_backupPath << QDir::separator()
+                                     << QLatin1String("backup") << i << QLatin1String(".bak");
+
+        QString fwn = QDir::toNativeSeparators(fwi->fileName());
+        if (fwn.isEmpty())
+            fwn = fw->windowTitle();
+
+        backupMap.insert(fwn, formBackupName);
+
+        QFile file(formBackupName.replace(m_backupPath, m_backupTmpPath));
+        if (file.open(QFile::WriteOnly)){
+            QString contents = fixResourceFileBackupPath(fwi, backupDir);
+            if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fwi)) {
+                if (fwb->lineTerminatorMode() == qdesigner_internal::FormWindowBase::CRLFLineTerminator)
+                    contents.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+            }
+            const QByteArray utf8Array = contents.toUtf8();
+            if (file.write(utf8Array, utf8Array.size()) != utf8Array.size()) {
+                backupMap.remove(fwn);
+                qdesigner_internal::designerWarning(tr("The backup file %1 could not be written.").arg(file.fileName()));
+            } else
+                tmpFiles.append(formBackupName);
+
+            file.close();
+        }
+    }
+    qdesigner_internal::QSimpleResource::setWarningsEnabled(warningsEnabled);
+    if(!tmpFiles.isEmpty()) {
+        const QStringList backupFiles = backupDir.entryList(QDir::Files);
+        if(!backupFiles.isEmpty()) {
+            QStringListIterator it(backupFiles);
+            while (it.hasNext())
+                backupDir.remove(it.next());
+        }
+
+        QStringListIterator it(tmpFiles);
+        while (it.hasNext()) {
+            const QString tmpName = it.next();
+            QString name(tmpName);
+            name.replace(m_backupTmpPath, m_backupPath);
+            QFile tmpFile(tmpName);
+            if (!tmpFile.copy(name))
+                qdesigner_internal::designerWarning(tr("The backup file %1 could not be written.").arg(name));
+            tmpFile.remove();
+        }
+
+        m_settings.setBackup(backupMap);
+    }
+}
+
+QString QDesignerActions::fixResourceFileBackupPath(QDesignerFormWindowInterface *fwi, const QDir& backupDir)
+{
+    const QString content = fwi->contents();
+    QDomDocument domDoc(QLatin1String("backup"));
+    if(!domDoc.setContent(content))
+        return content;
+
+    const QDomNodeList list = domDoc.elementsByTagName(QLatin1String("resources"));
+    if (list.isEmpty())
+        return content;
+
+    for (int i = 0; i < list.count(); i++) {
+        const QDomNode node = list.at(i);
+        if (!node.isNull()) {
+            const QDomElement element = node.toElement();
+            if(!element.isNull() && element.tagName() == QLatin1String("resources")) {
+                QDomNode childNode = element.firstChild();
+                while (!childNode.isNull()) {
+                    QDomElement childElement = childNode.toElement();
+                    if(!childElement.isNull() && childElement.tagName() == QLatin1String("include")) {
+                        const QString attr = childElement.attribute(QLatin1String("location"));
+                        const QString path = fwi->absoluteDir().absoluteFilePath(attr);
+                        childElement.setAttribute(QLatin1String("location"), backupDir.relativeFilePath(path));
+                    }
+                    childNode = childNode.nextSibling();
+                }
+            }
+        }
+    }
+
+
+    return domDoc.toString();
+}
+
+QRect QDesignerActions::fixDialogRect(const QRect &rect) const
+{
+    QRect frameGeometry;
+    const QRect availableGeometry = QApplication::desktop()->availableGeometry(core()->topLevel());
+
+    if (workbench()->mode() == DockedMode) {
+        frameGeometry = core()->topLevel()->frameGeometry();
+    } else
+        frameGeometry = availableGeometry;
+
+    QRect dlgRect = rect;
+    dlgRect.moveCenter(frameGeometry.center());
+
+    // make sure that parts of the dialog are not outside of screen
+    dlgRect.moveBottom(qMin(dlgRect.bottom(), availableGeometry.bottom()));
+    dlgRect.moveRight(qMin(dlgRect.right(), availableGeometry.right()));
+    dlgRect.moveLeft(qMax(dlgRect.left(), availableGeometry.left()));
+    dlgRect.moveTop(qMax(dlgRect.top(), availableGeometry.top()));
+
+    return dlgRect;
+}
+
+void QDesignerActions::showStatusBarMessage(const QString &message) const
+{
+    if (workbench()->mode() == DockedMode) {
+        QStatusBar *bar = qDesigner->mainWindow()->statusBar();
+        if (bar && !bar->isHidden())
+            bar->showMessage(message, 3000);
+    }
+}
+
+void QDesignerActions::setBringAllToFrontVisible(bool visible)
+{
+      m_bringAllToFrontSeparator->setVisible(visible);
+      m_bringAllToFrontAction->setVisible(visible);
+}
+
+void QDesignerActions::setWindowListSeparatorVisible(bool visible)
+{
+    m_windowListSeparatorAction->setVisible(visible);
+}
+
+bool QDesignerActions::ensureBackupDirectories() {
+
+    if (m_backupPath.isEmpty()) {
+        // create names
+        m_backupPath = QDir::homePath();
+        m_backupPath += QDir::separator();
+        m_backupPath += QLatin1String(".designer");
+        m_backupPath += QDir::separator();
+        m_backupPath += QLatin1String("backup");
+        m_backupPath = QDir::toNativeSeparators(m_backupPath );
+
+        m_backupTmpPath = m_backupPath;
+        m_backupTmpPath += QDir::separator();
+        m_backupTmpPath += QLatin1String("tmp");
+        m_backupTmpPath = QDir::toNativeSeparators(m_backupTmpPath);
+    }
+
+    // ensure directories
+    const QDir backupDir(m_backupPath);
+    const QDir backupTmpDir(m_backupTmpPath);
+
+    if (!backupDir.exists()) {
+        if (!backupDir.mkpath(m_backupPath)) {
+            qdesigner_internal::designerWarning(tr("The backup directory %1 could not be created.").arg(m_backupPath));
+            return false;
+        }
+    }
+    if (!backupTmpDir.exists()) {
+        if (!backupTmpDir.mkpath(m_backupTmpPath)) {
+            qdesigner_internal::designerWarning(tr("The temporary backup directory %1 could not be created.").arg(m_backupTmpPath));
+            return false;
+        }
+    }
+    return true;
+}
+
+void QDesignerActions::showPreferencesDialog()
+{
+    PreferencesDialog preferencesDialog(workbench()->core(), m_core->topLevel());
+    preferencesDialog.exec();
+}
+
+void QDesignerActions::showAppFontDialog()
+{
+    if (!m_appFontDialog) // Might get deleted when switching ui modes
+        m_appFontDialog = new AppFontDialog(core()->topLevel());
+    m_appFontDialog->show();
+    m_appFontDialog->raise();
+}
+
+QPixmap QDesignerActions::createPreviewPixmap(QDesignerFormWindowInterface *fw)
+{
+    const QCursor oldCursor = core()->topLevel()->cursor();
+    core()->topLevel()->setCursor(Qt::WaitCursor);
+
+    QString errorMessage;
+    const QPixmap pixmap = m_previewManager->createPreviewPixmap(fw, QString(), &errorMessage);
+    core()->topLevel()->setCursor(oldCursor);
+    if (pixmap.isNull()) {
+        QMessageBox::warning(fw, tr("Preview failed"), errorMessage);
+    }
+    return pixmap;
+}
+
+qdesigner_internal::PreviewConfiguration QDesignerActions::previewConfiguration()
+{
+    qdesigner_internal::PreviewConfiguration pc;
+    QDesignerSharedSettings settings(core());
+    if (settings.isCustomPreviewConfigurationEnabled())
+        pc = settings.customPreviewConfiguration();
+    return pc;
+}
+
+void QDesignerActions::savePreviewImage()
+{
+    const char *format = "png";
+
+    QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+    if (!fw)
+        return;
+
+    QImage image;
+    const QString extension = QString::fromAscii(format);
+    const QString filter = tr("Image files (*.%1)").arg(extension);
+
+    QString suggestion = fw->fileName();
+    if (!suggestion.isEmpty()) {
+        suggestion = QFileInfo(suggestion).baseName();
+        suggestion += QLatin1Char('.');
+        suggestion += extension;
+    }
+    do {
+        const QString fileName  = getSaveFileNameWithExtension(fw, tr("Save Image"), suggestion, filter, extension);
+        if (fileName.isEmpty())
+            break;
+
+        if (image.isNull()) {
+            const QPixmap pixmap = createPreviewPixmap(fw);
+            if (pixmap.isNull())
+                break;
+
+            image = pixmap.toImage();
+        }
+
+        if (image.save(fileName, format)) {
+            showStatusBarMessage(tr("Saved image %1.").arg(QFileInfo(fileName).fileName()));
+            break;
+        }
+
+        QMessageBox box(QMessageBox::Warning, tr("Save Image"),
+                        tr("The file %1 could not be written.").arg( fileName),
+                        QMessageBox::Retry|QMessageBox::Cancel, fw);
+        if (box.exec() == QMessageBox::Cancel)
+            break;
+    } while (true);
+}
+
+void QDesignerActions::formWindowCountChanged()
+{
+    const bool enabled = m_core->formWindowManager()->formWindowCount() == 0;
+    /* Disable the application font action if there are form windows open
+     * as the reordering of the fonts sets font properties to 'changed'
+     * and overloaded fonts are not updated. */
+    static const QString disabledTip = tr("Please close all forms to enable the loading of additional fonts.");
+    m_appFontAction->setEnabled(enabled);
+    m_appFontAction->setStatusTip(enabled ? QString() : disabledTip);
+}
+
+void QDesignerActions::printPreviewImage()
+{
+#ifndef QT_NO_PRINTER
+    QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+    if (!fw)
+        return;
+
+    if (!m_printer)
+        m_printer = new QPrinter(QPrinter::HighResolution);
+
+    m_printer->setFullPage(false);
+
+    // Grab the image to be able to a suggest suitable orientation
+    const QPixmap pixmap = createPreviewPixmap(fw);
+    if (pixmap.isNull())
+        return;
+
+    const QSizeF pixmapSize = pixmap.size();
+    m_printer->setOrientation( pixmapSize.width() > pixmapSize.height() ?  QPrinter::Landscape :  QPrinter::Portrait);
+
+    // Printer parameters
+    QPrintDialog dialog(m_printer, fw);
+    if (!dialog.exec())
+        return;
+
+    const QCursor oldCursor = core()->topLevel()->cursor();
+    core()->topLevel()->setCursor(Qt::WaitCursor);
+    // Estimate of required scaling to make form look the same on screen and printer.
+    const double suggestedScaling = static_cast<double>(m_printer->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());
+
+    QPainter painter(m_printer);
+    painter.setRenderHint(QPainter::SmoothPixmapTransform);
+
+    // Clamp to page
+    const QRectF page =  painter.viewport();
+    const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
+    const double scaling = qMin(suggestedScaling, maxScaling);
+
+    const double xOffset = page.left() + qMax(0.0, (page.size().width()  - scaling * pixmapSize.width())  / 2.0);
+    const double yOffset = page.top()  + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
+
+    // Draw.
+    painter.translate(xOffset, yOffset);
+    painter.scale(scaling, scaling);
+    painter.drawPixmap(0, 0, pixmap);
+    core()->topLevel()->setCursor(oldCursor);
+
+    showStatusBarMessage(tr("Printed %1.").arg(QFileInfo(fw->fileName()).fileName()));
+#endif
+}
+
+QT_END_NAMESPACE
+#include <moc_qdesigner_actions.h>
diff --git a/src/designer/designer/qdesigner_actions.h b/src/designer/designer/qdesigner_actions.h
new file mode 100644 (file)
index 0000000..e659a5e
--- /dev/null
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_ACTIONS_H
+#define QDESIGNER_ACTIONS_H
+
+#include "assistantclient.h"
+#include "qdesigner_settings.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtGui/QPrinter>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWorkbench;
+
+class QDir;
+class QTimer;
+class QAction;
+class QActionGroup;
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class AppFontDialog;
+
+class QRect;
+class QWidget;
+class QPixmap;
+class QMenu;
+
+namespace qdesigner_internal {
+    class PreviewConfiguration;
+    class PreviewManager;
+}
+
+class QDesignerActions: public QObject
+{
+    Q_OBJECT
+public:
+    explicit QDesignerActions(QDesignerWorkbench *mainWindow);
+    virtual ~QDesignerActions();
+
+    QDesignerWorkbench *workbench() const;
+    QDesignerFormEditorInterface *core() const;
+
+    bool saveForm(QDesignerFormWindowInterface *fw);
+    bool readInForm(const QString &fileName);
+    bool writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName);
+
+    QActionGroup *fileActions() const;
+    QActionGroup *recentFilesActions() const;
+    QActionGroup *editActions() const;
+    QActionGroup *formActions() const;
+    QActionGroup *settingsActions() const;
+    QActionGroup *windowActions() const;
+    QActionGroup *toolActions() const;
+    QActionGroup *helpActions() const;
+    QActionGroup *uiMode() const;
+    QActionGroup *styleActions() const;
+    // file actions
+    QAction *openFormAction() const;
+    QAction *closeFormAction() const;
+    // window actions
+    QAction *minimizeAction() const;
+    // edit mode actions
+    QAction *editWidgets() const;
+    // form actions
+    QAction *previewFormAction() const;
+    QAction *viewCodeAction() const;
+
+    void setBringAllToFrontVisible(bool visible);
+    void setWindowListSeparatorVisible(bool visible);
+
+    bool openForm(QWidget *parent);
+
+    QString uiExtension() const;
+
+    // Boolean dynamic property set on actions to
+    // show them in the default toolbar layout
+    static const char *defaultToolbarPropertyName;
+
+public slots:
+    void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+    void createForm();
+    void slotOpenForm();
+    void helpRequested(const QString &manual, const QString &document);
+
+signals:
+    void useBigIcons(bool);
+
+private slots:
+    void saveForm();
+    void saveFormAs();
+    void saveAllForms();
+    void saveFormAsTemplate();
+    void viewCode();
+    void notImplementedYet();
+    void shutdown();
+    void editWidgetsSlot();
+    void openRecentForm();
+    void clearRecentFiles();
+    void closeForm();
+    void showDesignerHelp();
+    void showWhatsNew();
+    void aboutDesigner();
+    void showWidgetSpecificHelp();
+    void backupForms();
+    void showNewFormDialog(const QString &fileName);
+    void showPreferencesDialog();
+    void showAppFontDialog();
+    void savePreviewImage();
+    void printPreviewImage();
+    void updateCloseAction();
+    void formWindowCountChanged();
+    void formWindowSettingsChanged(QDesignerFormWindowInterface *fw);
+
+private:
+    QAction *createRecentFilesMenu();
+    bool saveFormAs(QDesignerFormWindowInterface *fw);
+    void fixActionContext();
+    void updateRecentFileActions();
+    void addRecentFile(const QString &fileName);
+    void showHelp(const QString &help);
+    void closePreview();
+    QRect fixDialogRect(const QRect &rect) const;
+    QString fixResourceFileBackupPath(QDesignerFormWindowInterface *fwi, const QDir& backupDir);
+    void showStatusBarMessage(const QString &message) const;
+    QActionGroup *createHelpActions();
+    bool ensureBackupDirectories();
+    QPixmap createPreviewPixmap(QDesignerFormWindowInterface *fw);
+    qdesigner_internal::PreviewConfiguration previewConfiguration();
+
+    enum { MaxRecentFiles = 10 };
+    QDesignerWorkbench *m_workbench;
+    QDesignerFormEditorInterface *m_core;
+    QDesignerSettings m_settings;
+    AssistantClient m_assistantClient;
+    QString m_openDirectory;
+    QString m_saveDirectory;
+
+
+    QString m_backupPath;
+    QString m_backupTmpPath;
+
+    QTimer* m_backupTimer;
+
+    QActionGroup *m_fileActions;
+    QActionGroup *m_recentFilesActions;
+    QActionGroup *m_editActions;
+    QActionGroup *m_formActions;
+    QActionGroup *m_settingsActions;
+    QActionGroup *m_windowActions;
+    QActionGroup *m_toolActions;
+    QActionGroup *m_helpActions;
+    QActionGroup *m_styleActions;
+
+    QAction *m_editWidgetsAction;
+
+    QAction *m_newFormAction;
+    QAction *m_openFormAction;
+    QAction *m_saveFormAction;
+    QAction *m_saveFormAsAction;
+    QAction *m_saveAllFormsAction;
+    QAction *m_saveFormAsTemplateAction;
+    QAction *m_closeFormAction;
+    QAction *m_savePreviewImageAction;
+    QAction *m_printPreviewAction;
+
+    QAction *m_quitAction;
+
+    QAction *m_previewFormAction;
+    QAction *m_viewCodeAction;
+
+    QAction *m_minimizeAction;
+    QAction *m_bringAllToFrontSeparator;
+    QAction *m_bringAllToFrontAction;
+    QAction *m_windowListSeparatorAction;
+
+    QAction *m_preferencesAction;
+    QAction *m_appFontAction;
+
+    QPointer<AppFontDialog> m_appFontDialog;
+
+#ifndef QT_NO_PRINTER
+    QPrinter *m_printer;
+#endif
+
+    qdesigner_internal::PreviewManager *m_previewManager;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_ACTIONS_H
diff --git a/src/designer/designer/qdesigner_appearanceoptions.cpp b/src/designer/designer/qdesigner_appearanceoptions.cpp
new file mode 100644 (file)
index 0000000..05f89e0
--- /dev/null
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_appearanceoptions.h"
+#include "ui_qdesigner_appearanceoptions.h"
+
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+// ---------------- AppearanceOptions
+AppearanceOptions::AppearanceOptions() :
+     uiMode(DockedMode)
+{
+}
+
+bool AppearanceOptions::equals(const AppearanceOptions &rhs) const
+{
+    return uiMode == rhs.uiMode && toolWindowFontSettings == rhs.toolWindowFontSettings;
+}
+
+void AppearanceOptions::toSettings(QDesignerSettings &settings) const
+{
+    settings.setUiMode(uiMode);
+    settings.setToolWindowFont(toolWindowFontSettings);
+}
+
+void AppearanceOptions::fromSettings(const QDesignerSettings &settings)
+{
+    uiMode = settings.uiMode();
+    toolWindowFontSettings = settings.toolWindowFont();
+}
+
+// ---------------- QDesignerAppearanceOptionsWidget
+QDesignerAppearanceOptionsWidget::QDesignerAppearanceOptionsWidget(QWidget *parent) :
+    QWidget(parent),
+    m_ui(new Ui::AppearanceOptionsWidget),
+    m_initialUIMode(NeutralMode)
+{
+    m_ui->setupUi(this);
+
+    m_ui->m_uiModeCombo->addItem(tr("Docked Window"), QVariant(DockedMode));
+    m_ui->m_uiModeCombo->addItem(tr("Multiple Top-Level Windows"), QVariant(TopLevelMode));
+    connect(m_ui->m_uiModeCombo, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(slotUiModeComboChanged()));
+
+    m_ui->m_fontPanel->setCheckable(true);
+    m_ui->m_fontPanel->setTitle(tr("Toolwindow Font"));
+
+}
+
+QDesignerAppearanceOptionsWidget::~QDesignerAppearanceOptionsWidget()
+{
+    delete m_ui;
+}
+
+UIMode QDesignerAppearanceOptionsWidget::uiMode() const
+{
+    return static_cast<UIMode>(m_ui->m_uiModeCombo->itemData(m_ui->m_uiModeCombo->currentIndex()).toInt());
+}
+
+AppearanceOptions QDesignerAppearanceOptionsWidget::appearanceOptions() const
+{
+    AppearanceOptions rc;
+    rc.uiMode = uiMode();
+    rc.toolWindowFontSettings.m_font = m_ui->m_fontPanel->selectedFont();
+    rc.toolWindowFontSettings.m_useFont = m_ui->m_fontPanel->isChecked();
+    rc.toolWindowFontSettings.m_writingSystem = m_ui->m_fontPanel->writingSystem();
+    return rc;
+}
+
+void QDesignerAppearanceOptionsWidget::setAppearanceOptions(const AppearanceOptions &ao)
+{
+    m_initialUIMode = ao.uiMode;
+    m_ui->m_uiModeCombo->setCurrentIndex(m_ui->m_uiModeCombo->findData(QVariant(ao.uiMode)));
+    m_ui->m_fontPanel->setWritingSystem(ao.toolWindowFontSettings.m_writingSystem);
+    m_ui->m_fontPanel->setSelectedFont(ao.toolWindowFontSettings.m_font);
+    m_ui->m_fontPanel->setChecked(ao.toolWindowFontSettings.m_useFont);
+}
+
+void QDesignerAppearanceOptionsWidget::slotUiModeComboChanged()
+{
+    emit uiModeChanged(m_initialUIMode != uiMode());
+}
+
+// ----------- QDesignerAppearanceOptionsPage
+QDesignerAppearanceOptionsPage::QDesignerAppearanceOptionsPage(QDesignerFormEditorInterface *core) :
+    m_core(core)
+{
+}
+
+QString QDesignerAppearanceOptionsPage::name() const
+{
+    //: Tab in preferences dialog
+    return QCoreApplication::translate("QDesignerAppearanceOptionsPage", "Appearance");
+}
+
+QWidget *QDesignerAppearanceOptionsPage::createPage(QWidget *parent)
+{
+    m_widget = new QDesignerAppearanceOptionsWidget(parent);
+    m_initialOptions.fromSettings(QDesignerSettings(m_core));
+    m_widget->setAppearanceOptions(m_initialOptions);
+    return m_widget;
+}
+
+void QDesignerAppearanceOptionsPage::apply()
+{
+    if (m_widget) {
+        const AppearanceOptions newOptions = m_widget->appearanceOptions();
+        if (newOptions != m_initialOptions) {
+            QDesignerSettings settings(m_core);
+            newOptions.toSettings(settings);
+            QTimer::singleShot(0, this, SIGNAL(settingsChangedDelayed()));
+            m_initialOptions = newOptions;
+        }
+    }
+}
+
+void QDesignerAppearanceOptionsPage::finish()
+{
+}
+
+QT_END_NAMESPACE
+
+#include <moc_qdesigner_appearanceoptions.h>
diff --git a/src/designer/designer/qdesigner_appearanceoptions.h b/src/designer/designer/qdesigner_appearanceoptions.h
new file mode 100644 (file)
index 0000000..69c78bb
--- /dev/null
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_APPEARANCEOPTIONS_H
+#define QDESIGNER_APPEARANCEOPTIONS_H
+
+#include "designer_enums.h"
+#include "qdesigner_toolwindow.h"
+
+#include <QtDesigner/abstractoptionspage_p.h>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettings;
+
+namespace Ui {
+    class AppearanceOptionsWidget;
+}
+
+/* AppearanceOptions data */
+struct AppearanceOptions {
+    AppearanceOptions();
+    bool equals(const AppearanceOptions&) const;
+    void toSettings(QDesignerSettings &) const;
+    void fromSettings(const QDesignerSettings &);
+
+    UIMode uiMode;
+    ToolWindowFontSettings toolWindowFontSettings;
+};
+
+inline bool operator==(const AppearanceOptions &ao1, const AppearanceOptions &ao2)
+{
+    return ao1.equals(ao2);
+}
+
+inline bool operator!=(const AppearanceOptions &ao1, const AppearanceOptions &ao2)
+{
+    return !ao1.equals(ao2);
+}
+
+/* QDesignerAppearanceOptionsWidget: Let the user edit AppearanceOptions */
+class QDesignerAppearanceOptionsWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit QDesignerAppearanceOptionsWidget(QWidget *parent = 0);
+    ~QDesignerAppearanceOptionsWidget();
+
+    AppearanceOptions appearanceOptions() const;
+    void setAppearanceOptions(const AppearanceOptions &ao);
+
+signals:
+    void uiModeChanged(bool modified);
+
+private slots:
+    void slotUiModeComboChanged();
+
+private:
+    UIMode uiMode() const;
+
+    Ui::AppearanceOptionsWidget *m_ui;
+    UIMode m_initialUIMode;
+};
+
+/* The options page for appearance options. Emits a Timer-0 delayed changed
+ * signal to allow the preferences dialog to close (and be deleted) before a
+ * possible switch from docked mode to top-level mode happens. (The switch
+ * would delete the main window, which the preference dialog is a child of
+ * -> BOOM) */
+
+class QDesignerAppearanceOptionsPage : public QObject, public QDesignerOptionsPageInterface
+{
+    Q_OBJECT
+
+public:
+    QDesignerAppearanceOptionsPage(QDesignerFormEditorInterface *core);
+
+    QString name() const;
+    QWidget *createPage(QWidget *parent);
+    virtual void apply();
+    virtual void finish();
+
+signals:
+    void settingsChangedDelayed();
+
+private:
+    QDesignerFormEditorInterface *m_core;
+    QPointer<QDesignerAppearanceOptionsWidget> m_widget;
+    AppearanceOptions m_initialOptions;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_APPEARANCEOPTIONS_H
diff --git a/src/designer/designer/qdesigner_appearanceoptions.ui b/src/designer/designer/qdesigner_appearanceoptions.ui
new file mode 100644 (file)
index 0000000..a5582f2
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AppearanceOptionsWidget</class>
+ <widget class="QWidget" name="AppearanceOptionsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>325</width>
+    <height>360</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="m_uiModeGroupBox">
+     <property name="title">
+      <string>User Interface Mode</string>
+     </property>
+     <layout class="QVBoxLayout">
+      <item>
+       <widget class="QComboBox" name="m_uiModeCombo"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="FontPanel" name="m_fontPanel"/>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>FontPanel</class>
+   <extends>QGroupBox</extends>
+   <header>fontpanel.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/designer/designer/qdesigner_formwindow.cpp b/src/designer/designer/qdesigner_formwindow.cpp
new file mode 100644 (file)
index 0000000..f4338f1
--- /dev/null
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_formwindow.h"
+#include "qdesigner_workbench.h"
+#include "formwindowbase_p.h"
+
+// sdk
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/abstractpropertyeditor.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/taskmenu.h>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QEvent>
+#include <QtCore/QFile>
+
+#include <QtGui/QAction>
+#include <QtGui/qevent.h>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/qundostack.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+QDesignerFormWindow::QDesignerFormWindow(QDesignerFormWindowInterface *editor, QDesignerWorkbench *workbench, QWidget *parent, Qt::WindowFlags flags)
+    : QWidget(parent, flags),
+      m_editor(editor),
+      m_workbench(workbench),
+      m_action(new QAction(this)),
+      m_initialized(false),
+      m_windowTitleInitialized(false)
+{
+    Q_ASSERT(workbench);
+
+    setMaximumSize(0xFFF, 0xFFF);
+    QDesignerFormEditorInterface *core = workbench->core();
+
+    if (m_editor) {
+        m_editor->setParent(this);
+    } else {
+        m_editor = core->formWindowManager()->createFormWindow(this);
+    }
+
+    QVBoxLayout *l = new QVBoxLayout(this);
+    l->setMargin(0);
+    l->addWidget(m_editor);
+
+    m_action->setCheckable(true);
+
+    connect(m_editor->commandHistory(), SIGNAL(indexChanged(int)), this, SLOT(updateChanged()));
+    connect(m_editor, SIGNAL(geometryChanged()), this, SLOT(geometryChanged()));
+    qdesigner_internal::FormWindowBase::setupDefaultAction(m_editor);
+}
+
+QDesignerFormWindow::~QDesignerFormWindow()
+{
+    if (workbench())
+        workbench()->removeFormWindow(this);
+}
+
+QAction *QDesignerFormWindow::action() const
+{
+    return m_action;
+}
+
+void QDesignerFormWindow::changeEvent(QEvent *e)
+{
+    switch (e->type()) {
+        case QEvent::WindowTitleChange:
+            m_action->setText(windowTitle().remove(QLatin1String("[*]")));
+            break;
+        case QEvent::WindowIconChange:
+            m_action->setIcon(windowIcon());
+            break;
+    case QEvent::WindowStateChange: {
+        const  QWindowStateChangeEvent *wsce =  static_cast<const QWindowStateChangeEvent *>(e);
+        const bool wasMinimized = Qt::WindowMinimized & wsce->oldState();
+        const bool isMinimizedNow = isMinimized();
+        if (wasMinimized != isMinimizedNow )
+            emit minimizationStateChanged(m_editor, isMinimizedNow);
+    }
+        break;
+        default:
+            break;
+    }
+    QWidget::changeEvent(e);
+}
+
+QRect QDesignerFormWindow::geometryHint() const
+{
+    const QPoint point(0, 0);
+    // If we have a container, we want to be just as big.
+    // QMdiSubWindow attempts to resize its children to sizeHint() when switching user interface modes.
+    if (QWidget *mainContainer = m_editor->mainContainer())
+        return QRect(point, mainContainer->size());
+
+    return QRect(point, sizeHint());
+}
+
+QDesignerFormWindowInterface *QDesignerFormWindow::editor() const
+{
+    return m_editor;
+}
+
+QDesignerWorkbench *QDesignerFormWindow::workbench() const
+{
+    return m_workbench;
+}
+
+void QDesignerFormWindow::firstShow()
+{
+    // Set up handling of file name changes and set initial title.
+    if (!m_windowTitleInitialized) {
+        m_windowTitleInitialized = true;
+        if (m_editor) {
+            connect(m_editor, SIGNAL(fileNameChanged(QString)), this, SLOT(updateWindowTitle(QString)));
+            updateWindowTitle(m_editor->fileName());
+            updateChanged();
+        }
+    }
+    show();
+}
+
+int QDesignerFormWindow::getNumberOfUntitledWindows() const
+{
+    const int totalWindows = m_workbench->formWindowCount();
+    if (!totalWindows)
+        return 0;
+
+    int maxUntitled = 0;
+    // Find the number of untitled windows excluding ourselves.
+    // Do not fall for 'untitled.ui', match with modified place holder.
+    // This will cause some problems with i18n, but for now I need the string to be "static"
+    QRegExp rx(QLatin1String("untitled( (\\d+))?\\[\\*\\]"));
+    for (int i = 0; i < totalWindows; ++i) {
+        QDesignerFormWindow *fw =  m_workbench->formWindow(i);
+        if (fw != this) {
+            const QString title = m_workbench->formWindow(i)->windowTitle();
+            if (rx.indexIn(title) != -1) {
+                if (maxUntitled == 0)
+                    ++maxUntitled;
+                if (rx.captureCount() > 1) {
+                    const QString numberCapture = rx.cap(2);
+                    if (!numberCapture.isEmpty())
+                        maxUntitled = qMax(numberCapture.toInt(), maxUntitled);
+                }
+            }
+        }
+    }
+    return maxUntitled;
+}
+
+void QDesignerFormWindow::updateWindowTitle(const QString &fileName)
+{
+    if (!m_windowTitleInitialized) {
+        m_windowTitleInitialized = true;
+        if (m_editor)
+            connect(m_editor, SIGNAL(fileNameChanged(QString)), this, SLOT(updateWindowTitle(QString)));
+    }
+
+    QString fileNameTitle;
+    if (fileName.isEmpty()) {
+        fileNameTitle = QLatin1String("untitled");
+        if (const int maxUntitled = getNumberOfUntitledWindows()) {
+            fileNameTitle += QLatin1Char(' ');
+            fileNameTitle += QString::number(maxUntitled + 1);
+        }
+    } else {
+        fileNameTitle = QFileInfo(fileName).fileName();
+    }
+
+    if (const QWidget *mc = m_editor->mainContainer()) {
+        setWindowIcon(mc->windowIcon());
+        setWindowTitle(tr("%1 - %2[*]").arg(mc->windowTitle()).arg(fileNameTitle));
+    } else {
+        setWindowTitle(fileNameTitle);
+    }
+}
+
+void QDesignerFormWindow::closeEvent(QCloseEvent *ev)
+{
+    if (m_editor->isDirty()) {
+        raise();
+        QMessageBox box(QMessageBox::Information, tr("Save Form?"),
+                tr("Do you want to save the changes to this document before closing?"),
+                QMessageBox::Discard | QMessageBox::Cancel | QMessageBox::Save, m_editor);
+        box.setInformativeText(tr("If you don't save, your changes will be lost."));
+        box.setWindowModality(Qt::WindowModal);
+        static_cast<QPushButton *>(box.button(QMessageBox::Save))->setDefault(true);
+
+        switch (box.exec()) {
+            case QMessageBox::Save: {
+                bool ok = workbench()->saveForm(m_editor);
+                ev->setAccepted(ok);
+                m_editor->setDirty(!ok);
+                break;
+            }
+            case QMessageBox::Discard:
+                m_editor->setDirty(false); // Not really necessary, but stops problems if we get close again.
+                ev->accept();
+                break;
+            case QMessageBox::Cancel:
+                ev->ignore();
+                break;
+        }
+    }
+}
+
+void QDesignerFormWindow::updateChanged()
+{
+    // Sometimes called after form window destruction.
+    if (m_editor) {
+        setWindowModified(m_editor->isDirty());
+        updateWindowTitle(m_editor->fileName());
+    }
+}
+
+void QDesignerFormWindow::resizeEvent(QResizeEvent *rev)
+{
+    if(m_initialized) {
+        m_editor->setDirty(true);
+        setWindowModified(true);
+    }
+
+    m_initialized = true;
+    QWidget::resizeEvent(rev);
+}
+
+void QDesignerFormWindow::geometryChanged()
+{
+    // If the form window changes, re-update the geometry of the current widget in the property editor.
+    // Note that in the case of layouts, non-maincontainer widgets must also be updated,
+    // so, do not do it for the main container only
+    const QDesignerFormEditorInterface *core = m_editor->core();
+    QObject *object = core->propertyEditor()->object();
+    if (object == 0 || !object->isWidgetType())
+        return;
+    static const QString geometryProperty = QLatin1String("geometry");
+    const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object);
+    const int geometryIndex = sheet->indexOf(geometryProperty);
+    if (geometryIndex == -1)
+        return;
+    core->propertyEditor()->setPropertyValue(geometryProperty, sheet->property(geometryIndex));
+}
+
+QT_END_NAMESPACE
+#include <moc_qdesigner_formwindow.h>
diff --git a/src/designer/designer/qdesigner_formwindow.h b/src/designer/designer/qdesigner_formwindow.h
new file mode 100644 (file)
index 0000000..0ef63ac
--- /dev/null
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_FORMWINDOW_H
+#define QDESIGNER_FORMWINDOW_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWorkbench;
+class QDesignerFormWindowInterface;
+
+class QDesignerFormWindow: public QWidget
+{
+    Q_OBJECT
+public:
+    QDesignerFormWindow(QDesignerFormWindowInterface *formWindow, QDesignerWorkbench *workbench,
+                        QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+    void firstShow();
+
+    virtual ~QDesignerFormWindow();
+
+    QAction *action() const;
+    QDesignerWorkbench *workbench() const;
+    QDesignerFormWindowInterface *editor() const;
+
+    QRect geometryHint() const;
+
+public slots:
+    void updateChanged();
+
+private slots:
+    void updateWindowTitle(const QString &fileName);
+    void geometryChanged();
+
+signals:
+    void minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized);
+    void triggerAction();
+
+protected:
+    virtual void changeEvent(QEvent *e);
+    virtual void closeEvent(QCloseEvent *ev);
+    virtual void resizeEvent(QResizeEvent* rev);
+
+private:
+    int getNumberOfUntitledWindows() const;
+    QPointer<QDesignerFormWindowInterface> m_editor;
+    QPointer<QDesignerWorkbench> m_workbench;
+    QAction *m_action;
+    bool m_initialized;
+    bool m_windowTitleInitialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMWINDOW_H
diff --git a/src/designer/designer/qdesigner_pch.h b/src/designer/designer/qdesigner_pch.h
new file mode 100644 (file)
index 0000000..3935aac
--- /dev/null
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if defined __cplusplus
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QSettings>
+#include <QtCore/qdebug.h>
+#include <QtGui/qevent.h>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMessageBox>
+#include <QtGui/QVBoxLayout>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+
+#include "qdesigner.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_workbench.h"
+#endif
diff --git a/src/designer/designer/qdesigner_server.cpp b/src/designer/designer/qdesigner_server.cpp
new file mode 100644 (file)
index 0000000..52a6107
--- /dev/null
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+
+#include <QtNetwork/QHostAddress>
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+
+#include "qdesigner.h"
+#include "qdesigner_server.h"
+
+#include <qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+// ### review
+
+QDesignerServer::QDesignerServer(QObject *parent)
+    : QObject(parent)
+{
+    m_socket = 0;
+    m_server = new QTcpServer(this);
+    m_server->listen(QHostAddress::LocalHost, 0);
+    if (m_server->isListening())
+    {
+        connect(m_server, SIGNAL(newConnection()),
+                this, SLOT(handleNewConnection()));
+    }
+}
+
+QDesignerServer::~QDesignerServer()
+{
+}
+
+quint16 QDesignerServer::serverPort() const
+{
+    return m_server ? m_server->serverPort() : 0;
+}
+
+void QDesignerServer::sendOpenRequest(int port, const QStringList &files)
+{
+    QTcpSocket *sSocket = new QTcpSocket();
+    sSocket->connectToHost(QHostAddress::LocalHost, port);
+    if(sSocket->waitForConnected(3000))
+    {
+        foreach(const QString &file, files)
+        {
+            QFileInfo fi(file);
+            sSocket->write(fi.absoluteFilePath().toUtf8() + '\n');
+        }
+        sSocket->waitForBytesWritten(3000);
+        sSocket->close();
+    }
+    delete sSocket;
+}
+
+void QDesignerServer::readFromClient()
+{
+    while (m_socket->canReadLine()) {
+        QString file = QString::fromUtf8(m_socket->readLine());
+        if (!file.isNull()) {
+            file.remove(QLatin1Char('\n'));
+            file.remove(QLatin1Char('\r'));
+            qDesigner->postEvent(qDesigner, new QFileOpenEvent(file));
+        }
+    }
+}
+
+void QDesignerServer::socketClosed()
+{
+    m_socket = 0;
+}
+
+void QDesignerServer::handleNewConnection()
+{
+    // no need for more than one connection
+    if (m_socket == 0) {
+        m_socket = m_server->nextPendingConnection();
+        connect(m_socket, SIGNAL(readyRead()),
+                this, SLOT(readFromClient()));
+        connect(m_socket, SIGNAL(disconnected()),
+                this, SLOT(socketClosed()));
+    }
+}
+
+
+QDesignerClient::QDesignerClient(quint16 port, QObject *parent)
+: QObject(parent)
+{
+    m_socket = new QTcpSocket(this);
+    m_socket->connectToHost(QHostAddress::LocalHost, port);
+    connect(m_socket, SIGNAL(readyRead()),
+                this, SLOT(readFromSocket()));
+}
+
+QDesignerClient::~QDesignerClient()
+{
+    m_socket->close();
+    m_socket->flush();
+}
+
+void QDesignerClient::readFromSocket()
+{
+    while (m_socket->canReadLine()) {
+        QString file = QString::fromUtf8(m_socket->readLine());
+        if (!file.isNull()) {
+            file.remove(QLatin1Char('\n'));
+            file.remove(QLatin1Char('\r'));
+            if (QFile::exists(file))
+                qDesigner->postEvent(qDesigner, new QFileOpenEvent(file));
+        }
+    }
+}
+
+QT_END_NAMESPACE
+#include <moc_qdesigner_server.h>
diff --git a/src/designer/designer/qdesigner_server.h b/src/designer/designer/qdesigner_server.h
new file mode 100644 (file)
index 0000000..8b9ec51
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_SERVER_H
+#define QDESIGNER_SERVER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QTcpServer;
+class QTcpSocket;
+
+class QDesignerServer: public QObject
+{
+    Q_OBJECT
+public:
+    explicit QDesignerServer(QObject *parent = 0);
+    virtual ~QDesignerServer();
+
+    quint16 serverPort() const;
+
+    static void sendOpenRequest(int port, const QStringList &files);
+
+private slots:
+    void handleNewConnection();
+    void readFromClient();
+    void socketClosed();
+
+private:
+    QTcpServer *m_server;
+    QTcpSocket *m_socket;
+};
+
+class QDesignerClient: public QObject
+{
+    Q_OBJECT
+public:
+    explicit QDesignerClient(quint16 port, QObject *parent = 0);
+    virtual ~QDesignerClient();
+
+private slots:
+    void readFromSocket();
+
+private:
+    QTcpSocket *m_socket;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_SERVER_H
diff --git a/src/designer/designer/qdesigner_settings.cpp b/src/designer/designer/qdesigner_settings.cpp
new file mode 100644 (file)
index 0000000..8e8df24
--- /dev/null
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_workbench.h"
+
+#include <abstractformeditor.h>
+#include <abstractsettings_p.h>
+#include <qdesigner_utils_p.h>
+#include <previewmanager_p.h>
+
+#include <QtCore/QVariant>
+#include <QtCore/QDir>
+
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QStyle>
+#include <QtGui/QListView>
+
+#include <QtCore/qdebug.h>
+
+enum { debugSettings = 0 };
+
+QT_BEGIN_NAMESPACE
+
+static const char *newFormShowKey = "newFormDialog/ShowOnStartup";
+
+// Change the version whenever the arrangement changes significantly.
+static const char *mainWindowStateKey = "MainWindowState45";
+static const char *toolBarsStateKey = "ToolBarsState45";
+
+static const char *backupOrgListKey = "backup/fileListOrg";
+static const char *backupBakListKey = "backup/fileListBak";
+static const char *recentFilesListKey = "recentFilesList";
+
+QDesignerSettings::QDesignerSettings(QDesignerFormEditorInterface *core) :
+    qdesigner_internal::QDesignerSharedSettings(core)
+{
+}
+
+void QDesignerSettings::setValue(const QString &key, const QVariant &value)
+{
+    settings()->setValue(key, value);
+}
+
+QVariant QDesignerSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+    return settings()->value(key, defaultValue);
+}
+
+static inline QChar modeChar(UIMode mode)
+{
+    return QLatin1Char(static_cast<char>(mode) + '0');
+}
+
+void QDesignerSettings::saveGeometryFor(const QWidget *w)
+{
+    Q_ASSERT(w && !w->objectName().isEmpty());
+    QDesignerSettingsInterface *s = settings();
+    const bool visible = w->isVisible();
+    if (debugSettings)
+        qDebug() << Q_FUNC_INFO << w << "visible=" << visible;
+    s->beginGroup(w->objectName());
+    s->setValue(QLatin1String("visible"), visible);
+    s->setValue(QLatin1String("geometry"), w->saveGeometry());
+    s->endGroup();
+}
+
+void QDesignerSettings::restoreGeometry(QWidget *w, QRect fallBack) const
+{
+    Q_ASSERT(w && !w->objectName().isEmpty());
+    const QString key = w->objectName();
+    const QByteArray ba(settings()->value(key + QLatin1String("/geometry")).toByteArray());
+    const bool visible = settings()->value(key + QLatin1String("/visible"), true).toBool();
+
+    if (debugSettings)
+        qDebug() << Q_FUNC_INFO << w << fallBack << "visible=" << visible;
+    if (ba.isEmpty()) {
+        /// Apply default geometry, check for null and maximal size
+        if (fallBack.isNull())
+            fallBack = QRect(QPoint(0, 0), w->sizeHint());
+        if (fallBack.size() == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) {
+            w->setWindowState(w->windowState() | Qt::WindowMaximized);
+        } else {
+            w->move(fallBack.topLeft());
+            w->resize(fallBack.size());
+        }
+    } else {
+        w->restoreGeometry(ba);
+    }
+
+    if (visible)
+        w->show();
+}
+
+QStringList QDesignerSettings::recentFilesList() const
+{
+    return settings()->value(QLatin1String(recentFilesListKey)).toStringList();
+}
+
+void QDesignerSettings::setRecentFilesList(const QStringList &sl)
+{
+    settings()->setValue(QLatin1String(recentFilesListKey), sl);
+}
+
+void QDesignerSettings::setShowNewFormOnStartup(bool showIt)
+{
+    settings()->setValue(QLatin1String(newFormShowKey), showIt);
+}
+
+bool QDesignerSettings::showNewFormOnStartup() const
+{
+    return settings()->value(QLatin1String(newFormShowKey), true).toBool();
+}
+
+QByteArray QDesignerSettings::mainWindowState(UIMode mode) const
+{
+    return settings()->value(QLatin1String(mainWindowStateKey) + modeChar(mode)).toByteArray();
+}
+
+void QDesignerSettings::setMainWindowState(UIMode mode, const QByteArray &mainWindowState)
+{
+    settings()->setValue(QLatin1String(mainWindowStateKey) + modeChar(mode), mainWindowState);
+}
+
+QByteArray QDesignerSettings::toolBarsState(UIMode mode) const
+{
+    QString key = QLatin1String(toolBarsStateKey);
+    key += modeChar(mode);
+    return settings()->value(key).toByteArray();
+}
+
+void QDesignerSettings::setToolBarsState(UIMode mode, const QByteArray &toolBarsState)
+{
+    QString key = QLatin1String(toolBarsStateKey);
+    key += modeChar(mode);
+    settings()->setValue(key, toolBarsState);
+}
+
+void QDesignerSettings::clearBackup()
+{
+    QDesignerSettingsInterface *s = settings();
+    s->remove(QLatin1String(backupOrgListKey));
+    s->remove(QLatin1String(backupBakListKey));
+}
+
+void QDesignerSettings::setBackup(const QMap<QString, QString> &map)
+{
+    const QStringList org = map.keys();
+    const QStringList bak = map.values();
+
+    QDesignerSettingsInterface *s = settings();
+    s->setValue(QLatin1String(backupOrgListKey), org);
+    s->setValue(QLatin1String(backupBakListKey), bak);
+}
+
+QMap<QString, QString> QDesignerSettings::backup() const
+{
+    const QStringList org = settings()->value(QLatin1String(backupOrgListKey), QStringList()).toStringList();
+    const QStringList bak = settings()->value(QLatin1String(backupBakListKey), QStringList()).toStringList();
+
+    QMap<QString, QString> map;
+    const int orgCount = org.count();
+    for (int i = 0; i < orgCount; ++i)
+        map.insert(org.at(i), bak.at(i));
+
+    return map;
+}
+
+void QDesignerSettings::setUiMode(UIMode mode)
+{
+    QDesignerSettingsInterface *s = settings();
+    s->beginGroup(QLatin1String("UI"));
+    s->setValue(QLatin1String("currentMode"), mode);
+    s->endGroup();
+}
+
+UIMode QDesignerSettings::uiMode() const
+{
+#ifdef Q_WS_MAC
+    const UIMode defaultMode = TopLevelMode;
+#else
+    const UIMode defaultMode = DockedMode;
+#endif
+    UIMode uiMode = static_cast<UIMode>(value(QLatin1String("UI/currentMode"), defaultMode).toInt());
+    return uiMode;
+}
+
+void QDesignerSettings::setToolWindowFont(const ToolWindowFontSettings &fontSettings)
+{
+    QDesignerSettingsInterface *s = settings();
+    s->beginGroup(QLatin1String("UI"));
+    s->setValue(QLatin1String("font"), fontSettings.m_font);
+    s->setValue(QLatin1String("useFont"), fontSettings.m_useFont);
+    s->setValue(QLatin1String("writingSystem"), fontSettings.m_writingSystem);
+    s->endGroup();
+}
+
+ToolWindowFontSettings QDesignerSettings::toolWindowFont() const
+{
+    ToolWindowFontSettings fontSettings;
+    fontSettings.m_writingSystem =
+            static_cast<QFontDatabase::WritingSystem>(value(QLatin1String("UI/writingSystem"),
+                                                            QFontDatabase::Any).toInt());
+    fontSettings.m_font = qvariant_cast<QFont>(value(QLatin1String("UI/font")));
+    fontSettings.m_useFont =
+            settings()->value(QLatin1String("UI/useFont"), QVariant(false)).toBool();
+    return fontSettings;
+}
+
+QT_END_NAMESPACE
diff --git a/src/designer/designer/qdesigner_settings.h b/src/designer/designer/qdesigner_settings.h
new file mode 100644 (file)
index 0000000..b4c4c02
--- /dev/null
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_SETTINGS_H
+#define QDESIGNER_SETTINGS_H
+
+#include "designer_enums.h"
+#include <shared_settings_p.h>
+#include <QtCore/QMap>
+#include <QtCore/QRect>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettingsInterface;
+struct ToolWindowFontSettings;
+
+class QDesignerSettings : public qdesigner_internal::QDesignerSharedSettings
+{
+public:
+    QDesignerSettings(QDesignerFormEditorInterface *core);
+
+    void setValue(const QString &key, const QVariant &value);
+    QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+
+    void restoreGeometry(QWidget *w, QRect fallBack = QRect()) const;
+    void saveGeometryFor(const QWidget *w);
+
+    QStringList recentFilesList() const;
+    void setRecentFilesList(const QStringList &list);
+
+    void setShowNewFormOnStartup(bool showIt);
+    bool showNewFormOnStartup() const;
+
+    void setUiMode(UIMode mode);
+    UIMode uiMode() const;
+
+    void setToolWindowFont(const ToolWindowFontSettings &fontSettings);
+    ToolWindowFontSettings toolWindowFont() const;
+
+    QByteArray mainWindowState(UIMode mode) const;
+    void setMainWindowState(UIMode mode, const QByteArray &mainWindowState);
+
+    QByteArray toolBarsState(UIMode mode) const;
+    void setToolBarsState(UIMode mode, const QByteArray &mainWindowState);
+
+    void clearBackup();
+    void setBackup(const QMap<QString, QString> &map);
+    QMap<QString, QString> backup() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_SETTINGS_H
diff --git a/src/designer/designer/qdesigner_toolwindow.cpp b/src/designer/designer/qdesigner_toolwindow.cpp
new file mode 100644 (file)
index 0000000..86e55df
--- /dev/null
@@ -0,0 +1,439 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_workbench.h"
+
+#include <QtDesigner/abstractpropertyeditor.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractactioneditor.h>
+#include <QtDesigner/abstractobjectinspector.h>
+#include <QtDesigner/abstractwidgetbox.h>
+#include <QtDesigner/qdesigner_components.h>
+
+#include <QtCore/QEvent>
+#include <QtCore/QDebug>
+#include <QtGui/QAction>
+#include <QtGui/qevent.h>
+
+enum { debugToolWindow = 0 };
+
+QT_BEGIN_NAMESPACE
+
+// ---------------- QDesignerToolWindowFontSettings
+ToolWindowFontSettings::ToolWindowFontSettings() :
+    m_writingSystem(QFontDatabase::Any),
+    m_useFont(false)
+{
+}
+
+bool ToolWindowFontSettings::equals(const ToolWindowFontSettings &rhs) const
+{
+    return m_useFont == rhs.m_useFont &&
+           m_writingSystem == rhs.m_writingSystem &&
+           m_font == rhs.m_font;
+}
+
+// ---------------- QDesignerToolWindow
+QDesignerToolWindow::QDesignerToolWindow(QDesignerWorkbench *workbench,
+                                         QWidget *w,
+                                         const QString &objectName,
+                                         const QString &title,
+                                         const QString &actionObjectName,
+                                         Qt::DockWidgetArea dockAreaHint,
+                                         QWidget *parent,
+                                         Qt::WindowFlags flags) :
+    MainWindowBase(parent, flags),
+    m_dockAreaHint(dockAreaHint),
+    m_workbench(workbench),
+    m_action(new QAction(this))
+{
+    setObjectName(objectName);
+    setCentralWidget(w);
+
+    setWindowTitle(title);
+
+    m_action->setObjectName(actionObjectName);
+    m_action->setShortcutContext(Qt::ApplicationShortcut);
+    m_action->setText(title);
+    m_action->setCheckable(true);
+    connect(m_action, SIGNAL(triggered(bool)), this, SLOT(showMe(bool)));
+}
+
+void QDesignerToolWindow::showMe(bool v)
+{
+    // Access the QMdiSubWindow in MDI mode.
+    if (QWidget *target = m_workbench->mode() == DockedMode ? parentWidget() : this) {
+        if (v)
+            target->setWindowState(target->windowState() & ~Qt::WindowMinimized);
+        target->setVisible(v);
+    }
+}
+
+void QDesignerToolWindow::showEvent(QShowEvent *e)
+{
+    Q_UNUSED(e);
+
+    bool blocked = m_action->blockSignals(true);
+    m_action->setChecked(true);
+    m_action->blockSignals(blocked);
+}
+
+void QDesignerToolWindow::hideEvent(QHideEvent *e)
+{
+    Q_UNUSED(e);
+
+    bool blocked = m_action->blockSignals(true);
+    m_action->setChecked(false);
+    m_action->blockSignals(blocked);
+}
+
+QAction *QDesignerToolWindow::action() const
+{
+    return m_action;
+}
+
+void QDesignerToolWindow::changeEvent(QEvent *e)
+{
+    switch (e->type()) {
+        case QEvent::WindowTitleChange:
+            m_action->setText(windowTitle());
+            break;
+        case QEvent::WindowIconChange:
+            m_action->setIcon(windowIcon());
+            break;
+        default:
+            break;
+    }
+    QMainWindow::changeEvent(e);
+}
+
+QDesignerWorkbench *QDesignerToolWindow::workbench() const
+{
+    return m_workbench;
+}
+
+QRect QDesignerToolWindow::geometryHint() const
+{
+    return QRect();
+}
+
+QRect QDesignerToolWindow::availableToolWindowGeometry() const
+{
+    return m_workbench->availableGeometry();
+}
+
+//  ---------------------- PropertyEditorToolWindow
+
+static inline QWidget *createPropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+    QDesignerPropertyEditorInterface *widget = QDesignerComponents::createPropertyEditor(core, parent);
+    core->setPropertyEditor(widget);
+    return widget;
+}
+
+class PropertyEditorToolWindow : public QDesignerToolWindow
+{
+public:
+    explicit PropertyEditorToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+
+protected:
+    virtual void showEvent(QShowEvent *event);
+};
+
+PropertyEditorToolWindow::PropertyEditorToolWindow(QDesignerWorkbench *workbench) :
+    QDesignerToolWindow(workbench,
+                        createPropertyEditor(workbench->core()),
+                        QLatin1String("qt_designer_propertyeditor"),
+                        QDesignerToolWindow::tr("Property Editor"),
+                        QLatin1String("__qt_property_editor_action"),
+                        Qt::RightDockWidgetArea)
+{
+    action()->setShortcut(Qt::CTRL + Qt::Key_I);
+
+}
+
+QRect PropertyEditorToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+    const int spacing = 40;
+    const QSize sz(g.width() * 1/4, g.height() * 4/6);
+
+    const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+                           (g.top() + margin + g.height() * 1/6) + spacing,
+                           sz.width(), sz.height());
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << rc;
+    return rc;
+}
+
+void PropertyEditorToolWindow::showEvent(QShowEvent *event)
+{
+    if (QDesignerPropertyEditorInterface *e = workbench()->core()->propertyEditor()) {
+        // workaround to update the propertyeditor when it is not visible!
+        e->setObject(e->object()); // ### remove me
+    }
+
+    QDesignerToolWindow::showEvent(event);
+}
+
+//  ---------------------- ActionEditorToolWindow
+
+static inline QWidget *createActionEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+    QDesignerActionEditorInterface *widget = QDesignerComponents::createActionEditor(core, parent);
+    core->setActionEditor(widget);
+    return widget;
+}
+
+class ActionEditorToolWindow: public QDesignerToolWindow
+{
+public:
+    explicit ActionEditorToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+};
+
+ActionEditorToolWindow::ActionEditorToolWindow(QDesignerWorkbench *workbench) :
+    QDesignerToolWindow(workbench,
+                        createActionEditor(workbench->core()),
+                        QLatin1String("qt_designer_actioneditor"),
+                        QDesignerToolWindow::tr("Action Editor"),
+                        QLatin1String("__qt_action_editor_tool_action"),
+                        Qt::RightDockWidgetArea)
+{
+}
+
+QRect ActionEditorToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+
+    const QSize sz(g.width() * 1/4, g.height() * 1/6);
+
+    const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+                            g.top() + margin,
+                            sz.width(), sz.height());
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << rc;
+    return rc;
+}
+
+//  ---------------------- ObjectInspectorToolWindow
+
+static inline QWidget *createObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+    QDesignerObjectInspectorInterface *widget = QDesignerComponents::createObjectInspector(core, parent);
+    core->setObjectInspector(widget);
+    return widget;
+}
+
+class ObjectInspectorToolWindow: public QDesignerToolWindow
+{
+public:
+    explicit ObjectInspectorToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+};
+
+ObjectInspectorToolWindow::ObjectInspectorToolWindow(QDesignerWorkbench *workbench) :
+    QDesignerToolWindow(workbench,
+                        createObjectInspector(workbench->core()),
+                        QLatin1String("qt_designer_objectinspector"),
+                        QDesignerToolWindow::tr("Object Inspector"),
+                        QLatin1String("__qt_object_inspector_tool_action"),
+                        Qt::RightDockWidgetArea)
+{
+}
+
+QRect ObjectInspectorToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+
+    const QSize sz(g.width() * 1/4, g.height() * 1/6);
+
+    const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+                            g.top() + margin,
+                           sz.width(), sz.height());
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << rc;
+    return rc;
+}
+
+//  ---------------------- ResourceEditorToolWindow
+
+class ResourceEditorToolWindow: public QDesignerToolWindow
+{
+public:
+    explicit ResourceEditorToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+};
+
+ResourceEditorToolWindow::ResourceEditorToolWindow(QDesignerWorkbench *workbench)  :
+    QDesignerToolWindow(workbench,
+                        QDesignerComponents::createResourceEditor(workbench->core(), 0),
+                        QLatin1String("qt_designer_resourceeditor"),
+                        QDesignerToolWindow::tr("Resource Browser"),
+                        QLatin1String("__qt_resource_editor_tool_action"),
+                        Qt::RightDockWidgetArea)
+{
+}
+
+QRect ResourceEditorToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+
+    const QSize sz(g.width() * 1/3, g.height() * 1/6);
+    QRect r(QPoint(0, 0), sz);
+    r.moveCenter(g.center());
+    r.moveBottom(g.bottom() - margin);
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << r;
+    return r;
+}
+
+//  ---------------------- SignalSlotEditorToolWindow
+
+class SignalSlotEditorToolWindow: public QDesignerToolWindow
+{
+public:
+    explicit SignalSlotEditorToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+};
+
+SignalSlotEditorToolWindow::SignalSlotEditorToolWindow(QDesignerWorkbench *workbench) :
+    QDesignerToolWindow(workbench,
+                        QDesignerComponents::createSignalSlotEditor(workbench->core(), 0),
+                        QLatin1String("qt_designer_signalsloteditor"),
+                        QDesignerToolWindow::tr("Signal/Slot Editor"),
+                        QLatin1String("__qt_signal_slot_editor_tool_action"),
+                        Qt::RightDockWidgetArea)
+{
+}
+
+QRect SignalSlotEditorToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+
+    const QSize sz(g.width() * 1/3, g.height() * 1/6);
+    QRect r(QPoint(0, 0), sz);
+    r.moveCenter(g.center());
+    r.moveTop(margin + g.top());
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << r;
+    return r;
+}
+
+//  ---------------------- WidgetBoxToolWindow
+
+static inline QWidget *createWidgetBox(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+    QDesignerWidgetBoxInterface *widget = QDesignerComponents::createWidgetBox(core, parent);
+    core->setWidgetBox(widget);
+    return widget;
+}
+
+class WidgetBoxToolWindow: public QDesignerToolWindow
+{
+public:
+    explicit WidgetBoxToolWindow(QDesignerWorkbench *workbench);
+
+    virtual QRect geometryHint() const;
+};
+
+WidgetBoxToolWindow::WidgetBoxToolWindow(QDesignerWorkbench *workbench) :
+    QDesignerToolWindow(workbench,
+                        createWidgetBox(workbench->core()),
+                        QLatin1String("qt_designer_widgetbox"),
+                        QDesignerToolWindow::tr("Widget Box"),
+                        QLatin1String("__qt_widget_box_tool_action"),
+                        Qt::LeftDockWidgetArea)
+{
+}
+
+QRect WidgetBoxToolWindow::geometryHint() const
+{
+    const QRect g = availableToolWindowGeometry();
+    const int margin = workbench()->marginHint();
+    const  QRect rc = QRect(g.left() + margin,
+                            g.top() + margin,
+                            g.width() * 1/4, g.height() * 5/6);
+    if (debugToolWindow)
+        qDebug() << Q_FUNC_INFO << rc;
+    return rc;
+}
+
+// -- Factory
+QDesignerToolWindow *QDesignerToolWindow::createStandardToolWindow(StandardToolWindow which,
+                                                                   QDesignerWorkbench *workbench)
+{
+    switch (which) {
+    case ActionEditor:
+        return new ActionEditorToolWindow(workbench);
+    case ResourceEditor:
+        return new ResourceEditorToolWindow(workbench);
+    case SignalSlotEditor:
+        return new SignalSlotEditorToolWindow(workbench);
+    case PropertyEditor:
+        return new PropertyEditorToolWindow(workbench);
+    case ObjectInspector:
+        return new ObjectInspectorToolWindow(workbench);
+    case WidgetBox:
+        return new WidgetBoxToolWindow(workbench);
+    default:
+        break;
+    }
+    return 0;
+}
+
+
+QT_END_NAMESPACE
+#include <moc_qdesigner_toolwindow.h>
diff --git a/src/designer/designer/qdesigner_toolwindow.h b/src/designer/designer/qdesigner_toolwindow.h
new file mode 100644 (file)
index 0000000..a261926
--- /dev/null
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_TOOLWINDOW_H
+#define QDESIGNER_TOOLWINDOW_H
+
+#include "mainwindow.h"
+
+#include <QtCore/QPointer>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+struct ToolWindowFontSettings {
+    ToolWindowFontSettings();
+    bool equals(const ToolWindowFontSettings &) const;
+
+    QFont m_font;
+    QFontDatabase::WritingSystem m_writingSystem;
+    bool m_useFont;
+};
+
+inline bool operator==(const ToolWindowFontSettings &tw1, const ToolWindowFontSettings &tw2)
+{
+    return tw1.equals(tw2);
+}
+
+inline bool operator!=(const ToolWindowFontSettings &tw1, const ToolWindowFontSettings &tw2)
+{
+    return !tw1.equals(tw2);
+}
+
+class QDesignerWorkbench;
+
+/* A tool window with an action that activates it. Note that in toplevel mode,
+ * the Widget box is a tool window as well as the applications' main window,
+ * So, we need to inherit from MainWindowBase. */
+
+class QDesignerToolWindow : public MainWindowBase
+{
+    Q_OBJECT
+protected:
+    explicit QDesignerToolWindow(QDesignerWorkbench *workbench,
+                                 QWidget *w,
+                                 const QString &objectName,
+                                 const QString &title,
+                                 const QString &actionObjectName,
+                                 Qt::DockWidgetArea dockAreaHint,
+                                 QWidget *parent = 0,
+                                 Qt::WindowFlags flags = Qt::Window);
+
+public:
+    // Note: The order influences the dock widget position.
+    enum StandardToolWindow { WidgetBox,  ObjectInspector, PropertyEditor,
+                              ResourceEditor, ActionEditor, SignalSlotEditor,
+                              StandardToolWindowCount };
+
+    static QDesignerToolWindow *createStandardToolWindow(StandardToolWindow which, QDesignerWorkbench *workbench);
+
+    QDesignerWorkbench *workbench() const;
+    QAction *action() const;
+
+    Qt::DockWidgetArea dockWidgetAreaHint() const { return m_dockAreaHint; }
+    virtual QRect geometryHint() const;
+
+private slots:
+    void showMe(bool);
+
+protected:
+    virtual void showEvent(QShowEvent *e);
+    virtual void hideEvent(QHideEvent *e);
+    virtual void changeEvent(QEvent *e);
+
+    QRect availableToolWindowGeometry() const;
+
+private:
+    const Qt::DockWidgetArea m_dockAreaHint;
+    QDesignerWorkbench *m_workbench;
+    QAction *m_action;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TOOLWINDOW_H
diff --git a/src/designer/designer/qdesigner_workbench.cpp b/src/designer/designer/qdesigner_workbench.cpp
new file mode 100644 (file)
index 0000000..3364cfa
--- /dev/null
@@ -0,0 +1,1111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_workbench.h"
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_appearanceoptions.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_formwindow.h"
+#include "appfontdialog.h"
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformwindowmanager.h>
+#include <QtDesigner/abstractformeditorplugin.h>
+#include <QtDesigner/abstractwidgetbox.h>
+#include <QtDesigner/abstractmetadatabase.h>
+
+#include <QtDesigner/qdesigner_components.h>
+#include <QtDesigner/qdesigner_integration_p.h>
+#include <QtDesigner/pluginmanager_p.h>
+#include <QtDesigner/formwindowbase_p.h>
+#include <QtDesigner/actioneditor_p.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QUrl>
+#include <QtCore/QTimer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/qdebug.h>
+
+#include <QtGui/QActionGroup>
+#include <QtGui/qevent.h>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QDockWidget>
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QToolBar>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+static const char *appFontPrefixC = "AppFonts";
+
+typedef QList<QAction *> ActionList;
+
+static QMdiSubWindow *mdiSubWindowOf(const QWidget *w)
+{
+    QMdiSubWindow *rc = qobject_cast<QMdiSubWindow *>(w->parentWidget());
+    Q_ASSERT(rc);
+    return rc;
+}
+
+static QDockWidget *dockWidgetOf(const QWidget *w)
+{
+    for (QWidget *parentWidget = w->parentWidget(); parentWidget ; parentWidget = parentWidget->parentWidget()) {
+        if (QDockWidget *dw = qobject_cast<QDockWidget *>(parentWidget)) {
+            return dw;
+        }
+    }
+    Q_ASSERT("Dock widget not found");
+    return 0;
+}
+
+// ------------ QDesignerWorkbench::Position
+QDesignerWorkbench::Position::Position(const QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset) :
+    m_minimized(mdiSubWindow->isShaded()),
+    m_position(mdiSubWindow->pos() + mdiAreaOffset)
+{
+}
+
+QDesignerWorkbench::Position::Position(const QDockWidget *dockWidget) :
+    m_minimized(dockWidget->isMinimized()),
+    m_position(dockWidget->pos())
+{
+}
+
+QDesignerWorkbench::Position::Position(const QWidget *topLevelWindow, const QPoint &desktopTopLeft)
+{
+    const QWidget *window =topLevelWindow->window ();
+    Q_ASSERT(window);
+    m_minimized = window->isMinimized();
+    m_position = window->pos() - desktopTopLeft;
+}
+
+void QDesignerWorkbench::Position::applyTo(QMdiSubWindow *mdiSubWindow,
+                                           const QPoint &mdiAreaOffset) const
+{
+    // QMdiSubWindow attempts to resize its children to sizeHint() when switching user interface modes.
+    // Restore old size
+    const QPoint mdiAreaPos =  QPoint(qMax(0, m_position.x() - mdiAreaOffset.x()),
+                                      qMax(0, m_position.y() - mdiAreaOffset.y()));
+    mdiSubWindow->move(mdiAreaPos);
+    const QSize decorationSize = mdiSubWindow->size() - mdiSubWindow->contentsRect().size();
+    mdiSubWindow->resize(mdiSubWindow->widget()->size() + decorationSize);
+    mdiSubWindow->show();
+    if (m_minimized) {
+        mdiSubWindow->showShaded();
+    }
+}
+
+void QDesignerWorkbench::Position::applyTo(QWidget *topLevelWindow, const QPoint &desktopTopLeft) const
+{
+    QWidget *window = topLevelWindow->window ();
+    const QPoint newPos = m_position + desktopTopLeft;
+    window->move(newPos);
+    if ( m_minimized) {
+        topLevelWindow->showMinimized();
+    } else {
+        topLevelWindow->show();
+    }
+}
+
+void QDesignerWorkbench::Position::applyTo(QDockWidget *dockWidget) const
+{
+    dockWidget->widget()->setVisible(true);
+    dockWidget->setVisible(!m_minimized);
+}
+
+static inline void addActionsToMenu(QMenu *m, const ActionList &al)
+{
+    const ActionList::const_iterator cend = al.constEnd();
+    for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
+        m->addAction(*it);
+}
+
+static inline QMenu *addMenu(QMenuBar *mb, const QString &title, const ActionList &al)
+{
+    QMenu *rc = mb->addMenu(title);
+    addActionsToMenu(rc, al);
+    return rc;
+}
+
+// -------- QDesignerWorkbench
+
+QDesignerWorkbench::QDesignerWorkbench()  :
+    m_core(QDesignerComponents::createFormEditor(this)),
+    m_windowActions(new QActionGroup(this)),
+    m_globalMenuBar(new QMenuBar),
+    m_mode(NeutralMode),
+    m_dockedMainWindow(0),
+    m_state(StateInitializing)
+{
+    QDesignerSettings settings(m_core);
+
+    (void) QDesignerComponents::createTaskMenu(core(), this);
+
+    initializeCorePlugins();
+    QDesignerComponents::initializePlugins(core());
+    m_actionManager = new QDesignerActions(this); // accesses plugin components
+
+    m_windowActions->setExclusive(true);
+    connect(m_windowActions, SIGNAL(triggered(QAction*)), this, SLOT(formWindowActionTriggered(QAction*)));
+
+    // Build main menu bar
+    addMenu(m_globalMenuBar, tr("&File"), m_actionManager->fileActions()->actions());
+
+    QMenu *editMenu = addMenu(m_globalMenuBar, tr("&Edit"), m_actionManager->editActions()->actions());
+    editMenu->addSeparator();
+    addActionsToMenu(editMenu, m_actionManager->toolActions()->actions());
+
+    QMenu *formMenu = addMenu(m_globalMenuBar, tr("F&orm"),  m_actionManager->formActions()->actions());
+    QMenu *previewSubMenu = new QMenu(tr("Preview in"), formMenu);
+    formMenu->insertMenu(m_actionManager->previewFormAction(), previewSubMenu);
+    addActionsToMenu(previewSubMenu, m_actionManager->styleActions()->actions());
+
+    QMenu *viewMenu = m_globalMenuBar->addMenu(tr("&View"));
+
+    addMenu(m_globalMenuBar, tr("&Settings"), m_actionManager->settingsActions()->actions());
+
+    m_windowMenu = addMenu(m_globalMenuBar, tr("&Window"), m_actionManager->windowActions()->actions());
+
+    addMenu(m_globalMenuBar, tr("&Help"), m_actionManager->helpActions()->actions());
+
+    //  Add the tools in view menu order
+    QActionGroup *viewActions = new QActionGroup(this);
+    viewActions->setExclusive(false);
+
+    for (int i = 0; i < QDesignerToolWindow::StandardToolWindowCount; i++) {
+        QDesignerToolWindow *toolWindow = QDesignerToolWindow::createStandardToolWindow(static_cast< QDesignerToolWindow::StandardToolWindow>(i), this);
+        m_toolWindows.push_back(toolWindow);
+        if (QAction *action = toolWindow->action()) {
+            viewMenu->addAction(action);
+            viewActions->addAction(action);
+        }
+        // The widget box becomes the main window in top level mode
+        if (i == QDesignerToolWindow::WidgetBox)
+            connect(toolWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
+    }
+    // Integration
+    m_integration = new qdesigner_internal::QDesignerIntegration(m_core, this);
+    connect(m_integration, SIGNAL(helpRequested(QString,QString)), m_actionManager, SLOT(helpRequested(QString,QString)));
+
+    // remaining view options (config toolbars)
+    viewMenu->addSeparator();
+    m_toolbarMenu = viewMenu->addMenu(tr("Toolbars"));
+
+    emit initialized();
+
+    connect(m_core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+                this, SLOT(updateWindowMenu(QDesignerFormWindowInterface*)));
+
+
+    { // Add application specific options pages
+        QDesignerAppearanceOptionsPage *appearanceOptions = new QDesignerAppearanceOptionsPage(m_core);
+        connect(appearanceOptions, SIGNAL(settingsChangedDelayed()), this, SLOT(restoreUISettings()));
+        QList<QDesignerOptionsPageInterface*> optionsPages = m_core->optionsPages();
+        optionsPages.push_front(appearanceOptions);
+        m_core->setOptionsPages(optionsPages);
+    }
+
+    restoreUISettings();
+    AppFontWidget::restore(m_core->settingsManager(), QLatin1String(appFontPrefixC));
+    m_state = StateUp;
+}
+
+QDesignerWorkbench::~QDesignerWorkbench()
+{
+    switch (m_mode) {
+    case NeutralMode:
+    case DockedMode:
+        qDeleteAll(m_toolWindows);
+        break;
+    case TopLevelMode: // Everything parented here
+        delete widgetBoxToolWindow();
+        break;
+    }
+}
+
+void QDesignerWorkbench::saveGeometriesForModeChange()
+{
+    m_Positions.clear();
+    switch (m_mode) {
+    case NeutralMode:
+        break;
+    case TopLevelMode: {
+        const QPoint desktopOffset = QApplication::desktop()->availableGeometry().topLeft();
+        foreach (QDesignerToolWindow *tw, m_toolWindows)
+            m_Positions.insert(tw, Position(tw, desktopOffset));
+        foreach (QDesignerFormWindow *fw, m_formWindows) {
+            m_Positions.insert(fw,  Position(fw, desktopOffset));
+        }
+    }
+        break;
+    case DockedMode: {
+        const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
+        foreach (QDesignerToolWindow *tw, m_toolWindows) {
+            m_Positions.insert(tw, Position(dockWidgetOf(tw)));
+        }
+        foreach (QDesignerFormWindow *fw, m_formWindows) {
+            m_Positions.insert(fw, Position(mdiSubWindowOf(fw), mdiAreaOffset));
+        }
+    }
+        break;
+    }
+}
+
+UIMode QDesignerWorkbench::mode() const
+{
+    return m_mode;
+}
+
+void QDesignerWorkbench::addFormWindow(QDesignerFormWindow *formWindow)
+{
+    // ### Q_ASSERT(formWindow->windowTitle().isEmpty() == false);
+
+    m_formWindows.append(formWindow);
+
+
+    m_actionManager->setWindowListSeparatorVisible(true);
+
+    if (QAction *action = formWindow->action()) {
+        m_windowActions->addAction(action);
+        m_windowMenu->addAction(action);
+        action->setChecked(true);
+    }
+
+    m_actionManager->minimizeAction()->setEnabled(true);
+    m_actionManager->minimizeAction()->setChecked(false);
+    connect(formWindow, SIGNAL(minimizationStateChanged(QDesignerFormWindowInterface*,bool)),
+            this, SLOT(minimizationStateChanged(QDesignerFormWindowInterface*,bool)));
+
+    m_actionManager->editWidgets()->trigger();
+}
+
+Qt::WindowFlags QDesignerWorkbench::magicalWindowFlags(const QWidget *widgetForFlags) const
+{
+    switch (m_mode) {
+        case TopLevelMode: {
+#ifdef Q_WS_MAC
+            if (qobject_cast<const QDesignerToolWindow *>(widgetForFlags))
+                return Qt::Tool;
+#else
+            Q_UNUSED(widgetForFlags);
+#endif
+            return Qt::Window;
+        }
+        case DockedMode:
+            return Qt::Window | Qt::WindowShadeButtonHint | Qt::WindowSystemMenuHint | Qt::WindowTitleHint;
+        case NeutralMode:
+            return Qt::Window;
+        default:
+            Q_ASSERT(0);
+            return 0;
+    }
+}
+
+QWidget *QDesignerWorkbench::magicalParent(const QWidget *w) const
+{
+    switch (m_mode) {
+        case TopLevelMode: {
+            // Use widget box as parent for all windows except self. This will
+            // result in having just one entry in the MS Windows task bar.
+            QWidget *widgetBoxWrapper = widgetBoxToolWindow();
+            return w == widgetBoxWrapper ? 0 : widgetBoxWrapper;
+        }
+        case DockedMode:
+            return m_dockedMainWindow->mdiArea();
+        case NeutralMode:
+            return 0;
+        default:
+            Q_ASSERT(0);
+            return 0;
+    }
+}
+
+void QDesignerWorkbench::switchToNeutralMode()
+{
+    QDesignerSettings settings(m_core);
+    saveGeometries(settings);
+    saveGeometriesForModeChange();
+
+    if (m_mode == TopLevelMode) {
+        delete m_topLevelData.toolbarManager;
+        m_topLevelData.toolbarManager = 0;
+        qDeleteAll(m_topLevelData.toolbars);
+        m_topLevelData.toolbars.clear();
+    }
+
+    m_mode = NeutralMode;
+
+    foreach (QDesignerToolWindow *tw, m_toolWindows) {
+        tw->setCloseEventPolicy(MainWindowBase::AcceptCloseEvents);
+        tw->setParent(0);
+    }
+
+    foreach (QDesignerFormWindow *fw, m_formWindows) {
+        fw->setParent(0);
+        fw->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+    }
+
+#ifndef Q_WS_MAC
+    m_globalMenuBar->setParent(0);
+#endif
+
+    m_core->setTopLevel(0);
+    qDesigner->setMainWindow(0);
+
+    delete m_dockedMainWindow;
+    m_dockedMainWindow = 0;
+}
+
+void QDesignerWorkbench::switchToDockedMode()
+{
+    if (m_mode == DockedMode)
+        return;
+
+    switchToNeutralMode();
+
+#ifdef Q_WS_X11
+    QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false);
+#endif
+#ifndef Q_WS_MAC
+    QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
+    widgetBoxWrapper->action()->setVisible(true);
+    widgetBoxWrapper->setWindowTitle(tr("Widget Box"));
+#endif
+
+    m_mode = DockedMode;
+    const QDesignerSettings settings(m_core);
+    m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows);
+    m_dockedMainWindow->setUnifiedTitleAndToolBarOnMac(true);
+    m_dockedMainWindow->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
+    connect(m_dockedMainWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
+    connect(m_dockedMainWindow, SIGNAL(fileDropped(QString)), this, SLOT(slotFileDropped(QString)));
+    connect(m_dockedMainWindow, SIGNAL(formWindowActivated(QDesignerFormWindow*)), this, SLOT(slotFormWindowActivated(QDesignerFormWindow*)));
+    m_dockedMainWindow->restoreSettings(settings, m_dockedMainWindow->addToolWindows(m_toolWindows), desktopGeometry());
+
+    m_core->setTopLevel(m_dockedMainWindow);
+
+#ifndef Q_WS_MAC
+    m_dockedMainWindow->setMenuBar(m_globalMenuBar);
+    m_globalMenuBar->show();
+#endif
+    qDesigner->setMainWindow(m_dockedMainWindow);
+
+    foreach (QDesignerFormWindow *fw, m_formWindows) {
+        QMdiSubWindow *subwin = m_dockedMainWindow->createMdiSubWindow(fw, magicalWindowFlags(fw),
+                                                                       m_actionManager->closeFormAction()->shortcut());
+        subwin->hide();
+        if (QWidget *mainContainer = fw->editor()->mainContainer())
+            resizeForm(fw, mainContainer);
+    }
+
+    m_actionManager->setBringAllToFrontVisible(false);
+    m_dockedMainWindow->show();
+    // Trigger adjustMDIFormPositions() delayed as viewport size is not yet known.
+
+    if (m_state != StateInitializing)
+        QMetaObject::invokeMethod(this, "adjustMDIFormPositions", Qt::QueuedConnection);
+}
+
+void QDesignerWorkbench::adjustMDIFormPositions()
+{
+    const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
+
+    foreach (QDesignerFormWindow *fw, m_formWindows) {
+        const PositionMap::const_iterator pit = m_Positions.constFind(fw);
+        if (pit != m_Positions.constEnd())
+            pit->applyTo(mdiSubWindowOf(fw), mdiAreaOffset);
+    }
+}
+
+void QDesignerWorkbench::switchToTopLevelMode()
+{
+    if (m_mode == TopLevelMode)
+        return;
+
+    // make sure that the widgetbox is visible if it is different from neutral.
+    QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
+    Q_ASSERT(widgetBoxWrapper);
+
+    switchToNeutralMode();
+    const QPoint desktopOffset = desktopGeometry().topLeft();
+    m_mode = TopLevelMode;
+
+    // The widget box is special, it gets the menubar and gets to be the main widget.
+
+    m_core->setTopLevel(widgetBoxWrapper);
+#ifdef Q_WS_X11
+    // For now the appmenu protocol does not make it possible to associate a
+    // menubar with all application windows. This means in top level mode you
+    // can only reach the menubar when the widgetbox window is active. Since
+    // this is quite inconvenient, better not use the native menubar in this
+    // configuration and keep the menubar in the widgetbox window.
+    QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+#endif
+#ifndef Q_WS_MAC
+    widgetBoxWrapper->setMenuBar(m_globalMenuBar);
+    widgetBoxWrapper->action()->setVisible(false);
+    widgetBoxWrapper->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
+    qDesigner->setMainWindow(widgetBoxWrapper);
+    widgetBoxWrapper->setWindowTitle(MainWindowBase::mainWindowTitle());
+#endif
+
+    const QDesignerSettings settings(m_core);
+    m_topLevelData.toolbars = MainWindowBase::createToolBars(m_actionManager, false);
+    m_topLevelData.toolbarManager = new ToolBarManager(widgetBoxWrapper, widgetBoxWrapper,
+                                                       m_toolbarMenu, m_actionManager,
+                                                       m_topLevelData.toolbars, m_toolWindows);
+    const int toolBarCount = m_topLevelData.toolbars.size();
+    for (int i = 0; i < toolBarCount; i++) {
+        widgetBoxWrapper->addToolBar(m_topLevelData.toolbars.at(i));
+        if (i == 3)
+            widgetBoxWrapper->insertToolBarBreak(m_topLevelData.toolbars.at(i));
+    }
+    m_topLevelData.toolbarManager->restoreState(settings.toolBarsState(m_mode), MainWindowBase::settingsVersion());
+    widgetBoxWrapper->restoreState(settings.mainWindowState(m_mode), MainWindowBase::settingsVersion());
+
+    bool found_visible_window = false;
+    foreach (QDesignerToolWindow *tw, m_toolWindows) {
+        tw->setParent(magicalParent(tw), magicalWindowFlags(tw));
+        settings.restoreGeometry(tw, tw->geometryHint());
+        tw->action()->setChecked(tw->isVisible());
+        found_visible_window |= tw->isVisible();
+    }
+
+    if (!m_toolWindows.isEmpty() && !found_visible_window)
+        m_toolWindows.first()->show();
+
+    m_actionManager->setBringAllToFrontVisible(true);
+
+    foreach (QDesignerFormWindow *fw, m_formWindows) {
+        fw->setParent(magicalParent(fw), magicalWindowFlags(fw));
+        fw->setAttribute(Qt::WA_DeleteOnClose, true);
+        const PositionMap::const_iterator pit = m_Positions.constFind(fw);
+        if (pit != m_Positions.constEnd()) pit->applyTo(fw, desktopOffset);
+        // Force an activate in order to refresh minimumSize, otherwise it will not be respected
+        if (QLayout *layout = fw->layout())
+            layout->invalidate();
+        if (QWidget *mainContainer = fw->editor()->mainContainer())
+            resizeForm(fw, mainContainer);
+    }
+}
+
+QDesignerFormWindowManagerInterface *QDesignerWorkbench::formWindowManager() const
+{
+    return m_core->formWindowManager();
+}
+
+QDesignerFormEditorInterface *QDesignerWorkbench::core() const
+{
+    return m_core;
+}
+
+int QDesignerWorkbench::toolWindowCount() const
+{
+    return m_toolWindows.count();
+}
+
+QDesignerToolWindow *QDesignerWorkbench::toolWindow(int index) const
+{
+    return m_toolWindows.at(index);
+}
+
+int QDesignerWorkbench::formWindowCount() const
+{
+    return m_formWindows.count();
+}
+
+QDesignerFormWindow *QDesignerWorkbench::formWindow(int index) const
+{
+    return m_formWindows.at(index);
+}
+
+QRect QDesignerWorkbench::desktopGeometry() const
+{
+    // Return geometry of the desktop designer is running in.
+    QWidget *widget = 0;
+    switch (m_mode) {
+    case DockedMode:
+        widget = m_dockedMainWindow;
+        break;
+    case TopLevelMode:
+        widget = widgetBoxToolWindow();
+        break;
+    case NeutralMode:
+        break;
+    }
+    const QDesktopWidget *desktop = qApp->desktop();
+    const int screenNumber = widget ? desktop->screenNumber(widget) : 0;
+    return desktop->availableGeometry(screenNumber);
+}
+
+QRect QDesignerWorkbench::availableGeometry() const
+{
+    if (m_mode == DockedMode)
+        return m_dockedMainWindow->mdiArea()->geometry();
+
+    const QDesktopWidget *desktop = qDesigner->desktop();
+    return desktop->availableGeometry(desktop->screenNumber(widgetBoxToolWindow()));
+}
+
+int QDesignerWorkbench::marginHint() const
+{    return 20;
+}
+
+void QDesignerWorkbench::slotFormWindowActivated(QDesignerFormWindow* fw)
+{
+    core()->formWindowManager()->setActiveFormWindow(fw->editor());
+}
+
+void QDesignerWorkbench::removeFormWindow(QDesignerFormWindow *formWindow)
+{
+    QDesignerFormWindowInterface *editor = formWindow->editor();
+    const bool loadOk = editor->mainContainer();
+    updateBackup(editor);
+    const int index = m_formWindows.indexOf(formWindow);
+    if (index != -1) {
+        m_formWindows.removeAt(index);
+    }
+
+    if (QAction *action = formWindow->action()) {
+        m_windowActions->removeAction(action);
+        m_windowMenu->removeAction(action);
+    }
+
+    if (m_formWindows.empty()) {
+        m_actionManager->setWindowListSeparatorVisible(false);
+        // Show up new form dialog unless closing
+        if (loadOk && m_state == StateUp
+            && QDesignerSettings(m_core).showNewFormOnStartup()) {
+            QTimer::singleShot(200, m_actionManager, SLOT(createForm()));
+        }
+    }
+}
+
+void QDesignerWorkbench::initializeCorePlugins()
+{
+    QList<QObject*> plugins = QPluginLoader::staticInstances();
+    plugins += core()->pluginManager()->instances();
+
+    foreach (QObject *plugin, plugins) {
+        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
+            if (!formEditorPlugin->isInitialized())
+                formEditorPlugin->initialize(core());
+        }
+    }
+}
+
+void QDesignerWorkbench::saveSettings() const
+{
+    QDesignerSettings settings(m_core);
+    settings.clearBackup();
+    saveGeometries(settings);
+    AppFontWidget::save(m_core->settingsManager(), QLatin1String(appFontPrefixC));
+}
+
+void QDesignerWorkbench::saveGeometries(QDesignerSettings &settings) const
+{
+    switch (m_mode) {
+    case DockedMode:
+        m_dockedMainWindow->saveSettings(settings);
+        break;
+    case TopLevelMode:
+        settings.setToolBarsState(m_mode, m_topLevelData.toolbarManager->saveState(MainWindowBase::settingsVersion()));
+        settings.setMainWindowState(m_mode, widgetBoxToolWindow()->saveState(MainWindowBase::settingsVersion()));
+        foreach (const QDesignerToolWindow *tw, m_toolWindows)
+            settings.saveGeometryFor(tw);
+        break;
+    case NeutralMode:
+        break;
+    }
+}
+
+void QDesignerWorkbench::slotFileDropped(const QString &f)
+{
+    readInForm(f);
+}
+
+bool QDesignerWorkbench::readInForm(const QString &fileName) const
+{
+    return m_actionManager->readInForm(fileName);
+}
+
+bool QDesignerWorkbench::writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName) const
+{
+    return m_actionManager->writeOutForm(formWindow, fileName);
+}
+
+bool QDesignerWorkbench::saveForm(QDesignerFormWindowInterface *frm)
+{
+    return m_actionManager->saveForm(frm);
+}
+
+QDesignerFormWindow *QDesignerWorkbench::findFormWindow(QWidget *widget) const
+{
+    foreach (QDesignerFormWindow *formWindow, m_formWindows) {
+        if (formWindow->editor() == widget)
+            return formWindow;
+    }
+
+    return 0;
+}
+
+bool QDesignerWorkbench::handleClose()
+{
+    m_state = StateClosing;
+    QList<QDesignerFormWindow *> dirtyForms;
+    foreach (QDesignerFormWindow *w, m_formWindows) {
+        if (w->editor()->isDirty())
+            dirtyForms << w;
+    }
+
+    if (dirtyForms.size()) {
+        if (dirtyForms.size() == 1) {
+            if (!dirtyForms.at(0)->close()) {
+                m_state = StateUp;
+                return false;
+            }
+        } else {
+            int count = dirtyForms.size();
+            QMessageBox box(QMessageBox::Warning, tr("Save Forms?"),
+                    tr("There are %n forms with unsaved changes."
+                        " Do you want to review these changes before quitting?", "", count),
+                    QMessageBox::Cancel | QMessageBox::Discard | QMessageBox::Save);
+            box.setInformativeText(tr("If you do not review your documents, all your changes will be lost."));
+            box.button(QMessageBox::Discard)->setText(tr("Discard Changes"));
+            QPushButton *save = static_cast<QPushButton *>(box.button(QMessageBox::Save));
+            save->setText(tr("Review Changes"));
+            box.setDefaultButton(save);
+            switch (box.exec()) {
+            case QMessageBox::Cancel:
+                m_state = StateUp;
+                return false;
+            case QMessageBox::Save:
+               foreach (QDesignerFormWindow *fw, dirtyForms) {
+                   fw->show();
+                   fw->raise();
+                   if (!fw->close()) {
+                       m_state = StateUp;
+                       return false;
+                   }
+               }
+               break;
+            case QMessageBox::Discard:
+              foreach (QDesignerFormWindow *fw, dirtyForms) {
+                  fw->editor()->setDirty(false);
+                  fw->setWindowModified(false);
+              }
+              break;
+            }
+        }
+    }
+
+    foreach (QDesignerFormWindow *fw, m_formWindows)
+        fw->close();
+
+    saveSettings();
+    return true;
+}
+
+QDesignerActions *QDesignerWorkbench::actionManager() const
+{
+    return m_actionManager;
+}
+
+void QDesignerWorkbench::updateWindowMenu(QDesignerFormWindowInterface *fwi)
+{
+    bool minimizeChecked = false;
+    bool minimizeEnabled = false;
+    QDesignerFormWindow *activeFormWindow = 0;
+    do {
+        if (!fwi)
+        break;
+        activeFormWindow = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
+        if (!activeFormWindow)
+            break;
+
+        minimizeEnabled = true;
+        minimizeChecked = isFormWindowMinimized(activeFormWindow);
+    } while (false) ;
+
+    m_actionManager->minimizeAction()->setEnabled(minimizeEnabled);
+    m_actionManager->minimizeAction()->setChecked(minimizeChecked);
+
+    if (!m_formWindows.empty()) {
+        const QList<QDesignerFormWindow*>::const_iterator cend = m_formWindows.constEnd();
+        for (QList<QDesignerFormWindow*>::const_iterator it = m_formWindows.constBegin(); it != cend; ++it)
+            (*it)->action()->setChecked(*it == activeFormWindow);
+    }
+}
+
+void QDesignerWorkbench::formWindowActionTriggered(QAction *a)
+{
+    QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(a->parentWidget());
+    Q_ASSERT(fw);
+
+    if (isFormWindowMinimized(fw))
+        setFormWindowMinimized(fw, false);
+
+    if (m_mode == DockedMode) {
+        if (QMdiSubWindow *subWindow = qobject_cast<QMdiSubWindow *>(fw->parent())) {
+            m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWindow);
+        }
+    } else {
+        fw->activateWindow();
+        fw->raise();
+    }
+}
+
+void QDesignerWorkbench::closeAllToolWindows()
+{
+    foreach (QDesignerToolWindow *tw, m_toolWindows)
+        tw->hide();
+}
+
+bool QDesignerWorkbench::readInBackup()
+{
+    const QMap<QString, QString> backupFileMap = QDesignerSettings(m_core).backup();
+    if (backupFileMap.isEmpty())
+        return false;
+
+    const  QMessageBox::StandardButton answer =
+        QMessageBox::question(0, tr("Backup Information"),
+                                 tr("The last session of Designer was not terminated correctly. "
+                                       "Backup files were left behind. Do you want to load them?"),
+                                    QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
+    if (answer == QMessageBox::No)
+        return false;
+
+    const QString modifiedPlaceHolder = QLatin1String("[*]");
+    QMapIterator<QString, QString> it(backupFileMap);
+    while(it.hasNext()) {
+        it.next();
+
+        QString fileName = it.key();
+        fileName.remove(modifiedPlaceHolder);
+
+        if(m_actionManager->readInForm(it.value()))
+            formWindowManager()->activeFormWindow()->setFileName(fileName);
+
+    }
+    return true;
+}
+
+void QDesignerWorkbench::updateBackup(QDesignerFormWindowInterface* fwi)
+{
+    QString fwn = QDir::toNativeSeparators(fwi->fileName());
+    if (fwn.isEmpty())
+        fwn = fwi->parentWidget()->windowTitle();
+
+    QDesignerSettings settings(m_core);
+    QMap<QString, QString> map = settings.backup();
+    map.remove(fwn);
+    settings.setBackup(map);
+}
+
+namespace {
+    void raiseWindow(QWidget *w) {
+        if (w->isMinimized())
+            w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
+        w->raise();
+    }
+}
+
+void QDesignerWorkbench::bringAllToFront()
+{
+    if (m_mode !=  TopLevelMode)
+        return;
+    foreach(QDesignerToolWindow *tw, m_toolWindows)
+        raiseWindow(tw);
+    foreach(QDesignerFormWindow *dfw, m_formWindows)
+        raiseWindow(dfw);
+}
+
+// Resize a form window taking MDI decorations into account
+// Apply maximum size as there is no layout connection between
+// the form's main container and the integration's outer
+// container due to the tool widget stack.
+
+void QDesignerWorkbench::resizeForm(QDesignerFormWindow *fw, const QWidget *mainContainer) const
+{
+    const QSize containerSize = mainContainer->size();
+    const QSize containerMaximumSize = mainContainer->maximumSize();
+    if (m_mode != DockedMode) {
+        fw->resize(containerSize);
+        fw->setMaximumSize(containerMaximumSize);
+        return;
+    }
+    // get decorations and resize MDI
+    QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(fw->parent());
+    Q_ASSERT(mdiSubWindow);
+    const QSize decorationSize = mdiSubWindow->geometry().size() - mdiSubWindow->contentsRect().size();
+    mdiSubWindow->resize(containerSize + decorationSize);
+    // In Qt::RightToLeft mode, the window can grow to be partially hidden by the right border.
+    const int mdiAreaWidth = m_dockedMainWindow->mdiArea()->width();
+    if (qApp->layoutDirection() == Qt::RightToLeft && mdiSubWindow->geometry().right() >= mdiAreaWidth)
+        mdiSubWindow->move(mdiAreaWidth - mdiSubWindow->width(), mdiSubWindow->pos().y());
+
+    if (containerMaximumSize == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) {
+        mdiSubWindow->setMaximumSize(containerMaximumSize);
+    } else {
+        mdiSubWindow->setMaximumSize(containerMaximumSize + decorationSize);
+    }
+}
+
+
+// Load a form or return 0 and do cleanup. file name and editor file
+// name in case of loading a template file.
+
+QDesignerFormWindow * QDesignerWorkbench::loadForm(const QString &fileName,
+                                                   bool detectLineTermiantorMode,
+                                                   bool *uic3Converted,
+                                                   QString *errorMessage)
+{
+    QFile file(fileName);
+
+    qdesigner_internal::FormWindowBase::LineTerminatorMode mode = qdesigner_internal::FormWindowBase::NativeLineTerminator;
+
+    if (detectLineTermiantorMode) {
+        if (file.open(QFile::ReadOnly)) {
+            const QString text = QString::fromUtf8(file.readLine());
+            file.close();
+
+            const int lf = text.indexOf(QLatin1Char('\n'));
+            if (lf > 0 && text.at(lf-1) == QLatin1Char('\r')) {
+                mode = qdesigner_internal::FormWindowBase::CRLFLineTerminator;
+            } else if (lf >= 0) {
+                mode = qdesigner_internal::FormWindowBase::LFLineTerminator;
+            }
+        }
+    }
+
+    if (!file.open(QFile::ReadOnly|QFile::Text)) {
+        *errorMessage = tr("The file <b>%1</b> could not be opened.").arg(file.fileName());
+        return 0;
+    }
+
+
+    // Create a form
+    QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
+
+    QDesignerFormWindow *formWindow = new QDesignerFormWindow(/*formWindow=*/ 0, this);
+    addFormWindow(formWindow);
+    QDesignerFormWindowInterface *editor = formWindow->editor();
+    Q_ASSERT(editor);
+
+    // Temporarily set the file name. It is needed when converting a UIC 3 file.
+    // In this case, the file name will we be cleared on return to force a save box.
+    editor->setFileName(fileName);
+    editor->setContents(&file);
+
+    if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(editor))
+        fwb->setLineTerminatorMode(mode);
+
+    switch (m_mode) {
+    case DockedMode: {
+        // below code must be after above call to setContents(), because setContents() may popup warning dialogs which would cause
+        // mdi sub window activation (because of dialogs internal call to  processEvent or such)
+        // That activation could have worse consequences, e.g. NULL resource set for active form) before the form is loaded
+        QMdiSubWindow *subWin = m_dockedMainWindow->createMdiSubWindow(formWindow, magicalWindowFlags(formWindow), m_actionManager->closeFormAction()->shortcut());
+        m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWin);
+    }
+        break;
+    case TopLevelMode: {
+        const QRect formWindowGeometryHint = formWindow->geometryHint();
+        formWindow->setAttribute(Qt::WA_DeleteOnClose, true);
+        formWindow->setParent(magicalParent(formWindow), magicalWindowFlags(formWindow));
+        formWindow->resize(formWindowGeometryHint.size());
+        formWindow->move(availableGeometry().center() - formWindowGeometryHint.center());
+    }
+        break;
+    case NeutralMode:
+        break;
+    }
+
+    if (!editor->mainContainer()) {
+        removeFormWindow(formWindow);
+        formWindowManager->removeFormWindow(editor);
+        m_core->metaDataBase()->remove(editor);
+        *errorMessage = tr("The file <b>%1</b> is not a valid Designer UI file.").arg(file.fileName());
+        return 0;
+    }
+    *uic3Converted = editor->fileName().isEmpty();
+    // Did user specify another (missing) resource path -> set dirty.
+    const bool dirty = editor->property("_q_resourcepathchanged").toBool();
+    editor->setDirty(dirty);
+    resizeForm(formWindow, editor->mainContainer());
+    formWindowManager->setActiveFormWindow(editor);
+    return formWindow;
+}
+
+
+QDesignerFormWindow * QDesignerWorkbench::openForm(const QString &fileName, QString *errorMessage)
+{
+    bool uic3Converted;
+    QDesignerFormWindow *rc =loadForm(fileName, true, &uic3Converted, errorMessage);
+    if (!rc)
+        return 0;
+
+    if (!uic3Converted)
+        rc->editor()->setFileName(fileName);
+    rc->firstShow();
+    return rc;
+}
+
+QDesignerFormWindow * QDesignerWorkbench::openTemplate(const QString &templateFileName,
+                                                       const QString &editorFileName,
+                                                       QString *errorMessage)
+{
+    bool uic3Converted;
+    QDesignerFormWindow *rc =loadForm(templateFileName, false, &uic3Converted, errorMessage);
+    if (!rc)
+        return 0;
+
+    if (!uic3Converted)
+        rc->editor()->setFileName(editorFileName);
+
+    rc->firstShow();
+    return rc;
+}
+
+void QDesignerWorkbench::minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized)
+{
+    // refresh the minimize action state
+    if (core()->formWindowManager()->activeFormWindow() == formWindow) {
+        m_actionManager->minimizeAction()->setChecked(minimized);
+    }
+}
+
+void QDesignerWorkbench::toggleFormMinimizationState()
+{
+    QDesignerFormWindowInterface *fwi = core()->formWindowManager()->activeFormWindow();
+    if (!fwi || m_mode == NeutralMode)
+        return;
+    QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
+    Q_ASSERT(fw);
+    setFormWindowMinimized(fw, !isFormWindowMinimized(fw));
+}
+
+bool QDesignerWorkbench::isFormWindowMinimized(const QDesignerFormWindow *fw)
+{
+    switch (m_mode) {
+    case DockedMode:
+        return mdiSubWindowOf(fw)->isShaded();
+    case TopLevelMode:
+        return fw->window()->isMinimized();
+    default:
+        break;
+    }
+    return fw->isMinimized();
+}
+
+void QDesignerWorkbench::setFormWindowMinimized(QDesignerFormWindow *fw, bool minimized)
+{
+    switch (m_mode) {
+    case DockedMode: {
+        QMdiSubWindow *mdiSubWindow = mdiSubWindowOf(fw);
+        if (minimized) {
+            mdiSubWindow->showShaded();
+        } else {
+            mdiSubWindow->setWindowState(mdiSubWindow->windowState() & ~Qt::WindowMinimized);
+        }
+    }
+        break;
+    case TopLevelMode:        {
+        QWidget *window = fw->window();
+        if (window->isMinimized()) {
+            window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
+        } else {
+            window->showMinimized();
+        }
+    }
+        break;
+    default:
+        break;
+    }
+}
+
+void QDesignerWorkbench::restoreUISettings()
+{
+    UIMode mode = QDesignerSettings(m_core).uiMode();
+    switch (mode) {
+        case TopLevelMode:
+            switchToTopLevelMode();
+            break;
+        case DockedMode:
+            switchToDockedMode();
+            break;
+
+        default: Q_ASSERT(0);
+    }
+
+    ToolWindowFontSettings fontSettings = QDesignerSettings(m_core).toolWindowFont();
+    const QFont &font = fontSettings.m_useFont ? fontSettings.m_font : qApp->font();
+
+    if (font == m_toolWindows.front()->font())
+        return;
+
+    foreach(QDesignerToolWindow *tw, m_toolWindows)
+        tw->setFont(font);
+}
+
+void QDesignerWorkbench::handleCloseEvent(QCloseEvent *ev)
+{
+    ev->setAccepted(handleClose());
+    if (ev->isAccepted())
+        QMetaObject::invokeMethod(qDesigner, "quit", Qt::QueuedConnection);  // We're going down!
+}
+
+QDesignerToolWindow *QDesignerWorkbench::widgetBoxToolWindow() const
+{
+    return m_toolWindows.at(QDesignerToolWindow::WidgetBox);
+}
+
+QT_END_NAMESPACE
+#include <moc_qdesigner_workbench.h>
diff --git a/src/designer/designer/qdesigner_workbench.h b/src/designer/designer/qdesigner_workbench.h
new file mode 100644 (file)
index 0000000..9d0861e
--- /dev/null
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_WORKBENCH_H
+#define QDESIGNER_WORKBENCH_H
+
+#include "designer_enums.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QList>
+#include <QtCore/QRect>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerActions;
+class QDesignerToolWindow;
+class QDesignerFormWindow;
+class DockedMainWindow;
+class QDesignerSettings;
+
+class QAction;
+class QActionGroup;
+class QDockWidget;
+class QMenu;
+class QMenuBar;
+class QMainWindow;
+class QToolBar;
+class QMdiArea;
+class QMdiSubWindow;
+class QCloseEvent;
+class QFont;
+class QtToolBarManager;
+class ToolBarManager;
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerFormWindowManagerInterface;
+
+namespace qdesigner_internal {
+class QDesignerIntegration;
+}
+
+class QDesignerWorkbench: public QObject
+{
+    Q_OBJECT
+
+public:
+    QDesignerWorkbench();
+    virtual ~QDesignerWorkbench();
+
+    UIMode mode() const;
+
+    QDesignerFormEditorInterface *core() const;
+    QDesignerFormWindow *findFormWindow(QWidget *widget) const;
+
+    QDesignerFormWindow *openForm(const QString &fileName, QString *errorMessage);
+    QDesignerFormWindow *openTemplate(const QString &templateFileName,
+                                      const QString &editorFileName,
+                                      QString *errorMessage);
+
+    int toolWindowCount() const;
+    QDesignerToolWindow *toolWindow(int index) const;
+
+    int formWindowCount() const;
+    QDesignerFormWindow *formWindow(int index) const;
+
+    QDesignerActions *actionManager() const;
+
+    QActionGroup *modeActionGroup() const;
+
+    QRect availableGeometry() const;
+    QRect desktopGeometry() const;
+
+    int marginHint() const;
+
+    bool readInForm(const QString &fileName) const;
+    bool writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName) const;
+    bool saveForm(QDesignerFormWindowInterface *fw);
+    bool handleClose();
+    bool readInBackup();
+    void updateBackup(QDesignerFormWindowInterface* fwi);
+
+signals:
+    void modeChanged(UIMode mode);
+    void initialized();
+
+public slots:
+    void addFormWindow(QDesignerFormWindow *formWindow);
+    void removeFormWindow(QDesignerFormWindow *formWindow);
+    void bringAllToFront();
+    void toggleFormMinimizationState();
+
+private slots:
+    void switchToNeutralMode();
+    void switchToDockedMode();
+    void switchToTopLevelMode();
+    void initializeCorePlugins();
+    void handleCloseEvent(QCloseEvent *);
+    void slotFormWindowActivated(QDesignerFormWindow* fw);
+    void updateWindowMenu(QDesignerFormWindowInterface *fw);
+    void formWindowActionTriggered(QAction *a);
+    void adjustMDIFormPositions();
+    void minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized);
+
+    void restoreUISettings();
+    void slotFileDropped(const QString &f);
+
+private:
+    QWidget *magicalParent(const QWidget *w) const;
+    Qt::WindowFlags magicalWindowFlags(const QWidget *widgetForFlags) const;
+    QDesignerFormWindowManagerInterface *formWindowManager() const;
+    void closeAllToolWindows();
+    QDesignerToolWindow *widgetBoxToolWindow() const;
+    QDesignerFormWindow *loadForm(const QString &fileName, bool detectLineTermiantorMode, bool *uic3Converted, QString *errorMessage);
+    void resizeForm(QDesignerFormWindow *fw,  const QWidget *mainContainer) const;
+    void saveGeometriesForModeChange();
+    void saveGeometries(QDesignerSettings &settings) const;
+
+    bool isFormWindowMinimized(const QDesignerFormWindow *fw);
+    void setFormWindowMinimized(QDesignerFormWindow *fw, bool minimized);
+    void saveSettings() const;
+
+    QDesignerFormEditorInterface *m_core;
+    qdesigner_internal::QDesignerIntegration *m_integration;
+
+    QDesignerActions *m_actionManager;
+    QActionGroup *m_windowActions;
+
+    QMenu *m_windowMenu;
+
+    QMenuBar *m_globalMenuBar;
+
+    struct TopLevelData {
+        ToolBarManager *toolbarManager;
+        QList<QToolBar *> toolbars;
+    };
+    TopLevelData m_topLevelData;
+
+    UIMode m_mode;
+    DockedMainWindow *m_dockedMainWindow;
+
+    QList<QDesignerToolWindow*> m_toolWindows;
+    QList<QDesignerFormWindow*> m_formWindows;
+
+    QMenu *m_toolbarMenu;
+
+    // Helper class to remember the position of a window while switching user
+    // interface modes.
+    class Position {
+    public:
+        Position(const QDockWidget *dockWidget);
+        Position(const QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset);
+        Position(const QWidget *topLevelWindow, const QPoint &desktopTopLeft);
+
+        void applyTo(QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset) const;
+        void applyTo(QWidget *topLevelWindow, const QPoint &desktopTopLeft) const;
+        void applyTo(QDockWidget *dockWidget) const;
+
+        QPoint position() const { return m_position; }
+    private:
+        bool m_minimized;
+        // Position referring to top-left corner (desktop in top-level mode or
+        // main window in MDI mode)
+        QPoint m_position;
+    };
+    typedef  QHash<QWidget*, Position> PositionMap;
+    PositionMap m_Positions;
+
+    enum State { StateInitializing, StateUp, StateClosing };
+    State m_state;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_WORKBENCH_H
diff --git a/src/designer/designer/qttoolbardialog/images/back.png b/src/designer/designer/qttoolbardialog/images/back.png
new file mode 100644 (file)
index 0000000..e58177f
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/back.png differ
diff --git a/src/designer/designer/qttoolbardialog/images/down.png b/src/designer/designer/qttoolbardialog/images/down.png
new file mode 100644 (file)
index 0000000..29d1d44
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/down.png differ
diff --git a/src/designer/designer/qttoolbardialog/images/forward.png b/src/designer/designer/qttoolbardialog/images/forward.png
new file mode 100644 (file)
index 0000000..34b91f0
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/forward.png differ
diff --git a/src/designer/designer/qttoolbardialog/images/minus.png b/src/designer/designer/qttoolbardialog/images/minus.png
new file mode 100644 (file)
index 0000000..d6f233d
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/minus.png differ
diff --git a/src/designer/designer/qttoolbardialog/images/plus.png b/src/designer/designer/qttoolbardialog/images/plus.png
new file mode 100644 (file)
index 0000000..40df113
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/plus.png differ
diff --git a/src/designer/designer/qttoolbardialog/images/up.png b/src/designer/designer/qttoolbardialog/images/up.png
new file mode 100644 (file)
index 0000000..e437312
Binary files /dev/null and b/src/designer/designer/qttoolbardialog/images/up.png differ
diff --git a/src/designer/designer/qttoolbardialog/qttoolbardialog.cmake b/src/designer/designer/qttoolbardialog/qttoolbardialog.cmake
new file mode 100644 (file)
index 0000000..c4b2e59
--- /dev/null
@@ -0,0 +1,11 @@
+set(DESIGNERBIN_SOURCES
+    ${DESIGNERBIN_SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/qttoolbardialog/qttoolbardialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/qttoolbardialog/qttoolbardialog.ui
+    ${CMAKE_CURRENT_SOURCE_DIR}/qttoolbardialog/qttoolbardialog.qrc
+)
+
+set(DESIGNERBIN_HEADERS
+    ${DESIGNERBIN_HEADERS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/qttoolbardialog/qttoolbardialog.h
+) 
diff --git a/src/designer/designer/qttoolbardialog/qttoolbardialog.cpp b/src/designer/designer/qttoolbardialog/qttoolbardialog.cpp
new file mode 100644 (file)
index 0000000..35ec677
--- /dev/null
@@ -0,0 +1,1871 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qttoolbardialog.h"
+#include "ui_qttoolbardialog.h"
+
+#include <QtCore/QSet>
+#include <QtGui/qevent.h>
+#include <QtGui/QAction>
+#include <QtGui/QToolBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtFullToolBarManagerPrivate;
+
+class QtFullToolBarManager : public QObject
+{
+    Q_OBJECT
+public:
+    QtFullToolBarManager(QObject *parent);
+    ~QtFullToolBarManager();
+
+    void setMainWindow(QMainWindow *mainWindow);
+    QMainWindow *mainWindow() const;
+
+    void addCategory(const QString &category);
+    bool hasCategory(const QString &category) const;
+    QStringList categories() const;
+    QList<QAction *> categoryActions(const QString &category) const;
+    QString actionCategory(QAction *action) const;
+
+    // only non-separator
+    void addAction(QAction *action, const QString &category);
+
+    void removeAction(QAction *action);
+
+    QSet<QAction *> actions() const;
+    bool isWidgetAction(QAction *action) const;
+
+    /*
+    Adds (registers) toolBar. Adds (registers) actions that already exists in toolBar.
+    Remembers toolbar and its actions as a default.
+    */
+    void addDefaultToolBar(QToolBar *toolBar, const QString &category);
+
+    void removeDefaultToolBar(QToolBar *toolBar);
+    // NULL on action list means separator.
+    QMap<QToolBar *, QList<QAction *> > defaultToolBars() const;
+    bool isDefaultToolBar(QToolBar *toolBar) const;
+
+    QToolBar *createToolBar(const QString &toolBarName);
+    void deleteToolBar(QToolBar *toolBar); // only those which were created, not added
+
+    QList<QAction *> actions(QToolBar *toolBar) const;
+
+    void setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions);
+    void setToolBar(QToolBar *toolBar, const QList<QAction *> &actions);
+
+    QMap<QToolBar *, QList<QAction *> > toolBarsActions() const;
+    QByteArray saveState(int version = 0) const;
+    bool restoreState(const QByteArray &state, int version = 0);
+
+public slots:
+
+    void resetToolBar(QToolBar *toolBar);
+    void resetAllToolBars();
+
+signals:
+    void toolBarCreated(QToolBar *toolBar);
+    void toolBarRemoved(QToolBar *toolBar);
+
+    /*
+    If QToolBarWidgetAction was in another tool bar and is inserted into
+    this toolBar, toolBarChanged is first emitted for other toolbar - without
+    that action. (Another approach may be that user first must call setToolBar
+    without that action for old tool bar)
+    */
+    void toolBarChanged(QToolBar *toolBar, const QList<QAction *> &actions);
+
+private:
+    QScopedPointer<QtFullToolBarManagerPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QtFullToolBarManager)
+    Q_DISABLE_COPY(QtFullToolBarManager)
+};
+
+class QtFullToolBarManagerPrivate
+{
+    class QtFullToolBarManager *q_ptr;
+    Q_DECLARE_PUBLIC(QtFullToolBarManager)
+
+public:
+
+    QToolBar *toolBarWidgetAction(QAction *action) const;
+    void removeWidgetActions(const QMap<QToolBar *, QList<QAction *> > &actions);
+
+    enum {
+        VersionMarker = 0xff,
+        ToolBarMarker = 0xfe,
+        CustomToolBarMarker = 0xfd,
+    };
+
+    void saveState(QDataStream &stream) const;
+    bool restoreState(QDataStream &stream) const;
+    QToolBar *findDefaultToolBar(const QString &objectName) const;
+    QAction *findAction(const QString &actionName) const;
+
+    QToolBar *toolBarByName(const QString &toolBarName) const;
+
+    QtFullToolBarManagerPrivate();
+
+    QMap<QString, QList<QAction *> > categoryToActions;
+    QMap<QAction *, QString>         actionToCategory;
+
+    QSet<QAction *> allActions;
+    QMap<QAction *, QToolBar *> widgetActions;
+    QSet<QAction *> regularActions;
+    QMap<QAction *, QList<QToolBar *> > actionToToolBars;
+
+    QMap<QToolBar *, QList<QAction *> > toolBars;
+    QMap<QToolBar *, QList<QAction *> > toolBarsWithSeparators;
+    QMap<QToolBar *, QList<QAction *> > defaultToolBars;
+    QList<QToolBar *> customToolBars;
+
+    QMainWindow *theMainWindow;
+};
+
+
+
+
+QtFullToolBarManagerPrivate::QtFullToolBarManagerPrivate()
+    : theMainWindow(0)
+{
+}
+
+QToolBar *QtFullToolBarManagerPrivate::toolBarWidgetAction(QAction *action) const
+{
+    if (widgetActions.contains(action))
+        return widgetActions.value(action);
+    return 0;
+}
+
+void QtFullToolBarManagerPrivate::removeWidgetActions(const QMap<QToolBar *, QList<QAction *> >
+            &actions)
+{
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = actions.constBegin();
+    while (itToolBar != actions.constEnd()) {
+        QToolBar *toolBar = itToolBar.key();
+        QList<QAction *> newActions = toolBars.value(toolBar);
+        QList<QAction *> newActionsWithSeparators = toolBarsWithSeparators.value(toolBar);
+
+        QList<QAction *> removedActions;
+        QList<QAction *> actionList = itToolBar.value();
+        QListIterator<QAction *> itAction(actionList);
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+            if (newActions.contains(action) && toolBarWidgetAction(action) == toolBar) {
+                newActions.removeAll(action);
+                newActionsWithSeparators.removeAll(action);
+                removedActions.append(action);
+            }
+        }
+
+        //emit q_ptr->toolBarChanged(toolBar, newActions);
+
+        toolBars.insert(toolBar, newActions);
+        toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+        QListIterator<QAction *> itRemovedAction(removedActions);
+        while (itRemovedAction.hasNext()) {
+            QAction *oldAction = itRemovedAction.next();
+            widgetActions.insert(oldAction, 0);
+            actionToToolBars[oldAction].removeAll(toolBar);
+        }
+
+        ++itToolBar;
+    }
+}
+
+void QtFullToolBarManagerPrivate::saveState(QDataStream &stream) const
+{
+    stream << (uchar) ToolBarMarker;
+    stream << defaultToolBars.size();
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
+                defaultToolBars.constBegin();
+    while (itToolBar != defaultToolBars.constEnd()) {
+        QToolBar *tb = itToolBar.key();
+        if (tb->objectName().isEmpty()) {
+            qWarning("QtToolBarManager::saveState(): 'objectName' not set for QToolBar "
+                "%p '%s', using 'windowTitle' instead",
+            tb, tb->windowTitle().toLocal8Bit().constData());
+            stream << tb->windowTitle();
+        } else {
+            stream << tb->objectName();
+        }
+
+        stream << toolBars[tb].size();
+        QListIterator<QAction *> itAction(toolBars[tb]);
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+
+            if (action) {
+                if (action->objectName().isEmpty()) {
+                    qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
+                                "%p '%s', using 'text' instead",
+                            action, action->text().toLocal8Bit().constData());
+                    stream << action->text();
+                } else {
+                    stream << action->objectName();
+                }
+            } else {
+                stream << QString();
+            }
+        }
+        ++itToolBar;
+    }
+
+
+    stream << (uchar) CustomToolBarMarker;
+    stream << toolBars.size() - defaultToolBars.size();
+    itToolBar = toolBars.constBegin();
+    while (itToolBar != toolBars.constEnd()) {
+        QToolBar *tb = itToolBar.key();
+        if (!defaultToolBars.contains(tb)) {
+            stream << tb->objectName();
+            stream << tb->windowTitle();
+
+            stream << toolBars[tb].size();
+            QListIterator<QAction *> itAction(toolBars[tb]);
+            while (itAction.hasNext()) {
+                QAction *action = itAction.next();
+
+                if (action) {
+                    if (action->objectName().isEmpty()) {
+                        qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
+                                    "%p '%s', using 'text' instead",
+                                action, action->text().toLocal8Bit().constData());
+                        stream << action->text();
+                    } else {
+                        stream << action->objectName();
+                    }
+                } else {
+                    stream << QString();
+                }
+            }
+        }
+        ++itToolBar;
+    }
+}
+
+bool QtFullToolBarManagerPrivate::restoreState(QDataStream &stream) const
+{
+    uchar tmarker;
+    stream >> tmarker;
+    if (tmarker != ToolBarMarker)
+        return false;
+
+    int toolBars;
+    stream >> toolBars;
+    for (int i = 0; i < toolBars; i++) {
+        QString objectName;
+        stream >> objectName;
+        int actionCount;
+        stream >> actionCount;
+        QList<QAction *> actions;
+        for (int j = 0; j < actionCount; j++) {
+            QString actionName;
+            stream >> actionName;
+
+            if (actionName.isEmpty())
+                actions.append(0);
+            else {
+                QAction *action = findAction(actionName);
+                if (action)
+                    actions.append(action);
+            }
+        }
+
+        QToolBar *toolBar = findDefaultToolBar(objectName);
+        if (toolBar)
+            q_ptr->setToolBar(toolBar, actions);
+    }
+
+
+
+    uchar ctmarker;
+    stream >> ctmarker;
+    if (ctmarker != CustomToolBarMarker)
+        return false;
+
+    QList<QToolBar *> oldCustomToolBars = customToolBars;
+
+    stream >> toolBars;
+    for (int i = 0; i < toolBars; i++) {
+        QString objectName;
+        QString toolBarName;
+        int actionCount;
+        stream >> objectName;
+        stream >> toolBarName;
+        stream >> actionCount;
+        QList<QAction *> actions;
+        for (int j = 0; j < actionCount; j++) {
+            QString actionName;
+            stream >> actionName;
+
+            if (actionName.isEmpty())
+                actions.append(0);
+            else {
+                QAction *action = findAction(actionName);
+                if (action)
+                    actions.append(action);
+            }
+        }
+
+        QToolBar *toolBar = toolBarByName(objectName);
+        if (toolBar) {
+            toolBar->setWindowTitle(toolBarName);
+            oldCustomToolBars.removeAll(toolBar);
+        }
+        else
+            toolBar = q_ptr->createToolBar(toolBarName);
+        if (toolBar) {
+            toolBar->setObjectName(objectName);
+            q_ptr->setToolBar(toolBar, actions);
+        }
+    }
+    QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
+    while (itToolBar.hasNext())
+        q_ptr->deleteToolBar(itToolBar.next());
+    return true;
+}
+
+QToolBar *QtFullToolBarManagerPrivate::findDefaultToolBar(const QString &objectName) const
+{
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
+                defaultToolBars.constBegin();
+    while (itToolBar != defaultToolBars.constEnd()) {
+        QToolBar *tb = itToolBar.key();
+        if (tb->objectName() == objectName)
+            return tb;
+
+        ++itToolBar;
+    }
+
+    qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar named "
+        "'%s', trying to match using 'windowTitle' instead.",
+        objectName.toLocal8Bit().constData());
+
+    itToolBar = defaultToolBars.constBegin();
+    while (itToolBar != defaultToolBars.constEnd()) {
+        QToolBar *tb = itToolBar.key();
+        if (tb->windowTitle() == objectName)
+            return tb;
+
+        ++itToolBar;
+    }
+    qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar with "
+        "matching 'windowTitle' (looking for '%s').",
+        objectName.toLocal8Bit().constData());
+
+    return 0;
+}
+
+QAction *QtFullToolBarManagerPrivate::findAction(const QString &actionName) const
+{
+    QSetIterator<QAction *> itAction(allActions);
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+
+        if (action->objectName() == actionName)
+            return action;
+    }
+    qWarning("QtToolBarManager::restoreState(): cannot find a QAction named "
+        "'%s', trying to match using 'text' instead.",
+        actionName.toLocal8Bit().constData());
+
+    itAction.toFront();
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+
+        if (action->text() == actionName)
+            return action;
+    }
+    qWarning("QtToolBarManager::restoreState(): cannot find a QAction with "
+        "matching 'text' (looking for '%s').",
+        actionName.toLocal8Bit().constData());
+
+    return 0;
+}
+
+QToolBar *QtFullToolBarManagerPrivate::toolBarByName(const QString &toolBarName) const
+{
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
+    while (itToolBar != toolBars.constEnd()) {
+        QToolBar *toolBar = itToolBar.key();
+        if (toolBar->objectName() == toolBarName)
+            return toolBar;
+
+        ++itToolBar;
+    }
+    return 0;
+}
+
+//////////////////////////////
+
+QtFullToolBarManager::QtFullToolBarManager(QObject *parent)
+    : QObject(parent), d_ptr(new QtFullToolBarManagerPrivate)
+{
+    d_ptr->q_ptr = this;
+}
+
+QtFullToolBarManager::~QtFullToolBarManager()
+{
+}
+
+void QtFullToolBarManager::setMainWindow(QMainWindow *mainWindow)
+{
+    d_ptr->theMainWindow = mainWindow;
+}
+
+QMainWindow *QtFullToolBarManager::mainWindow() const
+{
+    return d_ptr->theMainWindow;
+}
+
+void QtFullToolBarManager::addCategory(const QString &category)
+{
+    d_ptr->categoryToActions[category] = QList<QAction *>();
+}
+
+bool QtFullToolBarManager::hasCategory(const QString &category) const
+{
+    return d_ptr->categoryToActions.contains(category);
+}
+
+QStringList QtFullToolBarManager::categories() const
+{
+    return d_ptr->categoryToActions.keys();
+}
+
+QList<QAction *> QtFullToolBarManager::categoryActions(const QString &category) const
+{
+    QMap<QString, QList<QAction *> >::ConstIterator it =
+                d_ptr->categoryToActions.find(category);
+    if (it != d_ptr->categoryToActions.constEnd())
+        return it.value();
+    return QList<QAction *>();
+}
+
+QString QtFullToolBarManager::actionCategory(QAction *action) const
+{
+    QMap<QAction *, QString>::ConstIterator it = d_ptr->actionToCategory.find(action);
+    if (it != d_ptr->actionToCategory.constEnd())
+        return it.value();
+    return QString();
+}
+
+void QtFullToolBarManager::addAction(QAction *action, const QString &category)
+{
+    if (!action)
+        return;
+    if (action->isSeparator())
+        return;
+    if (d_ptr->allActions.contains(action))
+        return;
+    if (QLatin1String(action->metaObject()->className()) ==
+                QLatin1String("QToolBarWidgetAction"))
+        d_ptr->widgetActions.insert(action, 0);
+    else
+        d_ptr->regularActions.insert(action);
+    d_ptr->allActions.insert(action);
+    d_ptr->categoryToActions[category].append(action);
+    d_ptr->actionToCategory[action] = category;
+}
+
+void QtFullToolBarManager::removeAction(QAction *action)
+{
+    if (!d_ptr->allActions.contains(action))
+        return;
+
+    QList<QToolBar *> toolBars = d_ptr->actionToToolBars[action];
+    QListIterator<QToolBar *> itToolBar(toolBars);
+    while (itToolBar.hasNext()) {
+        QToolBar *toolBar = itToolBar.next();
+
+        d_ptr->toolBars[toolBar].removeAll(action);
+        d_ptr->toolBarsWithSeparators[toolBar].removeAll(action);
+
+        toolBar->removeAction(action);
+    }
+
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itDefault =
+            d_ptr->defaultToolBars.constBegin();
+    while (itDefault != d_ptr->defaultToolBars.constEnd()) {
+        if (itDefault.value().contains(action))
+            d_ptr->defaultToolBars[itDefault.key()].removeAll(action);
+
+        itDefault++;
+    }
+
+    d_ptr->allActions.remove(action);
+    d_ptr->widgetActions.remove(action);
+    d_ptr->regularActions.remove(action);
+    d_ptr->actionToToolBars.remove(action);
+
+    QString category = d_ptr->actionToCategory.value(action);
+    d_ptr->actionToCategory.remove(action);
+    d_ptr->categoryToActions[category].removeAll(action);
+
+    if (d_ptr->categoryToActions[category].isEmpty())
+        d_ptr->categoryToActions.remove(category);
+}
+
+QSet<QAction *> QtFullToolBarManager::actions() const
+{
+    return d_ptr->allActions;
+}
+
+bool QtFullToolBarManager::isWidgetAction(QAction *action) const
+{
+    if (d_ptr->widgetActions.contains(action))
+        return true;
+    return false;
+}
+
+void QtFullToolBarManager::addDefaultToolBar(QToolBar *toolBar, const QString &category)
+{
+    if (!toolBar)
+        return;
+    if (d_ptr->toolBars.contains(toolBar))
+        return;
+    // could be also checked if toolBar belongs to mainwindow
+
+    QList<QAction *> newActionsWithSeparators;
+    QList<QAction *> newActions;
+    QList<QAction *> actions = toolBar->actions();
+    QListIterator<QAction *> itAction(actions);
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+        addAction(action, category);
+        if (d_ptr->widgetActions.contains(action))
+            d_ptr->widgetActions.insert(action, toolBar);
+        newActionsWithSeparators.append(action);
+        if (action->isSeparator())
+            action = 0;
+        else
+            d_ptr->actionToToolBars[action].append(toolBar);
+        newActions.append(action);
+    }
+    d_ptr->defaultToolBars.insert(toolBar, newActions);
+    //Below could be done by call setToolBar() if we want signal emission here.
+    d_ptr->toolBars.insert(toolBar, newActions);
+    d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+}
+
+void QtFullToolBarManager::removeDefaultToolBar(QToolBar *toolBar)
+{
+    if (!d_ptr->defaultToolBars.contains(toolBar))
+        return;
+
+    QList<QAction *> defaultActions = d_ptr->defaultToolBars[toolBar];
+    setToolBar(toolBar, QList<QAction *>());
+    QListIterator<QAction *> itAction(defaultActions);
+    while (itAction.hasNext())
+        removeAction(itAction.next());
+
+    d_ptr->toolBars.remove(toolBar);
+    d_ptr->toolBarsWithSeparators.remove(toolBar);
+    d_ptr->defaultToolBars.remove(toolBar);
+
+    itAction.toFront();
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+        if (action)
+            toolBar->insertAction(0, action);
+        else
+            toolBar->insertSeparator(0);
+    }
+}
+
+QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::defaultToolBars() const
+{
+    return d_ptr->defaultToolBars;
+}
+
+bool QtFullToolBarManager::isDefaultToolBar(QToolBar *toolBar) const
+{
+    if (d_ptr->defaultToolBars.contains(toolBar))
+        return true;
+    return false;
+}
+
+QToolBar *QtFullToolBarManager::createToolBar(const QString &toolBarName)
+{
+    if (!mainWindow())
+        return 0;
+    QToolBar *toolBar = new QToolBar(toolBarName, mainWindow());
+    int i = 1;
+    const QString prefix = QLatin1String("_Custom_Toolbar_%1");
+    QString name = prefix.arg(i);
+    while (d_ptr->toolBarByName(name))
+        name = prefix.arg(++i);
+    toolBar->setObjectName(name);
+    mainWindow()->addToolBar(toolBar);
+    d_ptr->customToolBars.append(toolBar);
+    d_ptr->toolBars.insert(toolBar, QList<QAction *>());
+    d_ptr->toolBarsWithSeparators.insert(toolBar, QList<QAction *>());
+    return toolBar;
+}
+
+void QtFullToolBarManager::deleteToolBar(QToolBar *toolBar)
+{
+    if (!d_ptr->toolBars.contains(toolBar))
+        return;
+    if (d_ptr->defaultToolBars.contains(toolBar))
+        return;
+    setToolBar(toolBar, QList<QAction *>());
+    d_ptr->customToolBars.removeAll(toolBar);
+    d_ptr->toolBars.remove(toolBar);
+    d_ptr->toolBarsWithSeparators.remove(toolBar);
+    delete toolBar;
+}
+
+QList<QAction *> QtFullToolBarManager::actions(QToolBar *toolBar) const
+{
+    if (d_ptr->toolBars.contains(toolBar))
+        return d_ptr->toolBars.value(toolBar);
+    return QList<QAction *>();
+}
+
+void QtFullToolBarManager::setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions)
+{
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator it = actions.constBegin();
+    while (it != actions.constEnd()) {
+        setToolBar(it.key(), it.value());
+        ++it;
+    }
+}
+
+void QtFullToolBarManager::setToolBar(QToolBar *toolBar, const QList<QAction *> &actions)
+{
+    if (!toolBar)
+        return;
+    if (!d_ptr->toolBars.contains(toolBar))
+        return;
+
+    if (actions == d_ptr->toolBars[toolBar])
+        return;
+
+    QMap<QToolBar *, QList<QAction *> > toRemove;
+
+    QList<QAction *> newActions;
+    QListIterator<QAction *> itAction(actions);
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+        if (!action || (!newActions.contains(action) && d_ptr->allActions.contains(action)))
+            newActions.append(action);
+
+        QToolBar *oldToolBar = d_ptr->toolBarWidgetAction(action);
+        if (oldToolBar && oldToolBar != toolBar)
+            toRemove[oldToolBar].append(action);
+    }
+
+    d_ptr->removeWidgetActions(toRemove);
+
+    QList<QAction *> oldActions = d_ptr->toolBarsWithSeparators.value(toolBar);
+    QListIterator<QAction *> itOldAction(oldActions);
+    while (itOldAction.hasNext()) {
+        QAction *action = itOldAction.next();
+        /*
+        When addDefaultToolBar() separator actions could be checked if they are
+        inserted in other toolbars - if yes then create new one.
+        */
+        if (d_ptr->toolBarWidgetAction(action) == toolBar)
+            d_ptr->widgetActions.insert(action, 0);
+        toolBar->removeAction(action);
+        if (action->isSeparator())
+            delete action;
+        else
+            d_ptr->actionToToolBars[action].removeAll(toolBar);
+    }
+
+    QList<QAction *> newActionsWithSeparators;
+    QListIterator<QAction *> itNewActions(newActions);
+    while (itNewActions.hasNext()) {
+        QAction *action = itNewActions.next();
+        QAction *newAction = 0;
+        if (!action)
+            newAction = toolBar->insertSeparator(0);
+        if (d_ptr->allActions.contains(action)) {
+            toolBar->insertAction(0, action);
+            newAction = action;
+            d_ptr->actionToToolBars[action].append(toolBar);
+        }
+        newActionsWithSeparators.append(newAction);
+    }
+    d_ptr->toolBars.insert(toolBar, newActions);
+    d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+}
+
+QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::toolBarsActions() const
+{
+    return d_ptr->toolBars;
+}
+
+void QtFullToolBarManager::resetToolBar(QToolBar *toolBar)
+{
+    if (!isDefaultToolBar(toolBar))
+        return;
+    setToolBar(toolBar, defaultToolBars().value(toolBar));
+}
+
+void QtFullToolBarManager::resetAllToolBars()
+{
+    setToolBars(defaultToolBars());
+    QList<QToolBar *> oldCustomToolBars = d_ptr->customToolBars;
+    QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
+    while (itToolBar.hasNext()) {
+        deleteToolBar(itToolBar.next());
+    }
+}
+
+QByteArray QtFullToolBarManager::saveState(int version) const
+{
+    QByteArray data;
+    QDataStream stream(&data, QIODevice::WriteOnly);
+    stream << QtFullToolBarManagerPrivate::VersionMarker;
+    stream << version;
+    d_ptr->saveState(stream);
+    return data;
+}
+
+bool QtFullToolBarManager::restoreState(const QByteArray &state, int version)
+{
+    QByteArray sd = state;
+    QDataStream stream(&sd, QIODevice::ReadOnly);
+    int marker, v;
+    stream >> marker;
+    stream >> v;
+    if (marker != QtFullToolBarManagerPrivate::VersionMarker || v != version)
+        return false;
+    return d_ptr->restoreState(stream);
+}
+
+
+class QtToolBarManagerPrivate
+{
+    class QtToolBarManager *q_ptr;
+    Q_DECLARE_PUBLIC(QtToolBarManager)
+public:
+    QtFullToolBarManager *manager;
+};
+
+//////////////////////////////////////
+
+/*! \class QtToolBarManager
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtToolBarManager class provides toolbar management for
+    main windows.
+
+    The QtToolBarManager is typically used with a QtToolBarDialog
+    which allows the user to customize the toolbars for a given main
+    window. The QtToolBarDialog class's functionality is controlled by
+    an instance of the QtToolBarManager class, and the main window is
+    specified using the QtToolBarManager class's setMainWindow()
+    function.
+
+    The currently specified main window can be retrieved using the
+    mainWindow() function.
+
+    The toolbar manager holds lists of the given main window's actions
+    and toolbars, and can add actions and toolbars to these
+    lists using the addAction() and addToolBar() functions
+    respectively. The actions can in addition be categorized
+    acccording to the user's preferences. The toolbar manager can also
+    remove custom actions and toolbars using the removeAction() and
+    removeToolBar() functions.
+
+    Finally, the QtToolBarManager is able to save the customized state
+    of its toolbars using the saveState() function as well as restore
+    the toolbars' saved state using restoreState() function.
+
+    \sa QtToolBarDialog
+*/
+
+/*!
+    Creates a toolbar manager with the given \a parent.
+*/
+QtToolBarManager::QtToolBarManager(QObject *parent)
+    : QObject(parent), d_ptr(new QtToolBarManagerPrivate)
+{
+    d_ptr->q_ptr = this;
+
+    d_ptr->manager = new QtFullToolBarManager(this);
+}
+
+/*!
+    Destroys the toolbar manager.
+*/
+QtToolBarManager::~QtToolBarManager()
+{
+}
+
+/*!
+    Sets the main window upon which the toolbar manager operates, to
+    be the given \a mainWindow.
+*/
+void QtToolBarManager::setMainWindow(QMainWindow *mainWindow)
+{
+    d_ptr->manager->setMainWindow(mainWindow);
+}
+
+/*!
+    Returns the main window associated this toolbar manager.
+*/
+QMainWindow *QtToolBarManager::mainWindow() const
+{
+    return d_ptr->manager->mainWindow();
+}
+
+/*!
+    Adds the given \a action to the given \a category in the manager's
+    list of actions. If the \a category doesn't exist it is created.
+    Only non separator actions can be added. If the action is already
+    added to the list, the function doesn't do anything.
+
+    \sa removeAction()
+*/
+void QtToolBarManager::addAction(QAction *action, const QString &category)
+{
+    d_ptr->manager->addAction(action, category);
+}
+
+/*!
+    Removes the specified \a action from the manager's list of
+    actions. The action is also removed from all the registered
+    toolbars.  If the specified \a action is the only action in its
+    category, that category is removed as well.
+
+    \sa addAction()
+*/
+void QtToolBarManager::removeAction(QAction *action)
+{
+    d_ptr->manager->removeAction(action);
+}
+
+/*!
+    Adds the given \a toolBar to the manager's toolbar list.
+
+    All the \a toolBar's actions are automatically added to the given
+    \a category in the manager's list of actions if they're not
+    already there. The manager remembers which toolbar the actions
+    belonged to, so, when the \a toolBar is removed, its actions will
+    be removed as well.
+
+    Custom toolbars are created with the main window returned by
+    the mainWindow() function, as its parent.
+
+    \sa removeToolBar()
+*/
+void QtToolBarManager::addToolBar(QToolBar *toolBar, const QString &category)
+{
+    d_ptr->manager->addDefaultToolBar(toolBar, category);
+}
+
+/*!
+    Removes the specified \a toolBar from the manager's list. All the
+    actions that existed in the specified \a toolBar when it was
+    added are removed as well.
+
+    \sa addToolBar()
+*/
+void QtToolBarManager::removeToolBar(QToolBar *toolBar)
+{
+    d_ptr->manager->removeDefaultToolBar(toolBar);
+}
+
+/*!
+    Returns the manager's toolbar list.
+*/
+QList<QToolBar *> QtToolBarManager::toolBars() const
+{
+    return d_ptr->manager->toolBarsActions().keys();
+}
+
+/*
+void QtToolBarManager::resetToolBar(QToolBar *toolBar)
+{
+    d_ptr->manager->resetToolBar(toolBar);
+}
+
+void QtToolBarManager::resetAllToolBars()
+{
+    d_ptr->manager->resetAllToolBars();
+}
+*/
+
+/*!
+    Saves the state of the toolbar manager's toolbars. The \a version
+    number is stored as part of the data.
+
+    Identifies all the QToolBar and QAction objects by their object
+    name property. Ensure that this property is unique for each
+    QToolBar and QAction that you add using the QtToolBarManager.
+
+    Returns an identifier for the state which can be passed along with
+    the version number to the restoreState() function to restore the
+    saved state.
+
+    \sa restoreState()
+*/
+QByteArray QtToolBarManager::saveState(int version) const
+{
+    return d_ptr->manager->saveState(version);
+}
+
+/*!
+    Restores the saved state of the toolbar manager's toolbars.  The
+    \a version number is compared with the version number of the
+    stored \a state.
+
+    Returns true if the version numbers are matching and the toolbar
+    manager's state is restored; otherwise the toolbar manager's state
+    is left unchanged and the function returns false.
+
+    Note that the state of the toolbar manager's toolbars should be
+    restored before restoring the state of the main window's toolbars
+    and dockwidgets using the QMainWindow::restoreState() function. In
+    that way the restoreState() function can create the custom
+    toolbars before the QMainWindow::restoreState() function restores
+    the custom toolbars' positions.
+
+    \sa saveState()
+*/
+bool QtToolBarManager::restoreState(const QByteArray &state, int version)
+{
+    return d_ptr->manager->restoreState(state, version);
+}
+
+//////////////////////
+
+class ToolBarItem {
+public:
+    ToolBarItem() : tb(0) {}
+    ToolBarItem(QToolBar *toolBar) : tb(toolBar) {}
+    ToolBarItem(QToolBar *toolBar, const QString &toolBarName)
+            : tb(toolBar), tbName(toolBarName) {}
+    ToolBarItem(const QString &toolBarName) : tb(0), tbName(toolBarName) {}
+    QToolBar *toolBar() const
+        { return tb; }
+    void setToolBar(QToolBar *toolBar)
+        { tb = toolBar; }
+    QString toolBarName() const
+        { return tbName; }
+    void setToolBarName(const QString &toolBarName)
+        { tbName = toolBarName; }
+private:
+    QToolBar *tb;
+    QString tbName;
+};
+
+class QtToolBarDialogPrivate {
+    QtToolBarDialog *q_ptr;
+    Q_DECLARE_PUBLIC(QtToolBarDialog)
+public:
+    QtToolBarDialogPrivate()
+        : toolBarManager(0),
+          currentAction(0),
+          currentToolBar(0)
+          { }
+
+    ToolBarItem *createItem(QToolBar *toolBar);
+    ToolBarItem *createItem(const QString &toolBarName);
+    void deleteItem(ToolBarItem *item);
+
+    void newClicked();
+    void removeClicked();
+    void defaultClicked();
+    void okClicked();
+    void applyClicked();
+    void cancelClicked();
+    void upClicked();
+    void downClicked();
+    void leftClicked();
+    void rightClicked();
+    void renameClicked();
+    void toolBarRenamed(QListWidgetItem *item);
+    void currentActionChanged(QTreeWidgetItem *current);
+    void currentToolBarChanged(QListWidgetItem *current);
+    void currentToolBarActionChanged(QListWidgetItem *current);
+
+    void removeToolBar(ToolBarItem *item);
+    bool isDefaultToolBar(ToolBarItem *item) const;
+    void setButtons();
+    void clearOld();
+    void fillNew();
+    QtFullToolBarManager *toolBarManager;
+    QMap<ToolBarItem *, QList<QAction *> > currentState;
+    QMap<QToolBar *, ToolBarItem *> toolBarItems;
+    QSet<ToolBarItem *> createdItems;
+    QSet<ToolBarItem *> removedItems;
+
+    QSet<ToolBarItem *> allToolBarItems;
+
+    // static
+    QTreeWidgetItem *currentAction;
+    QMap<QAction *, QTreeWidgetItem *> actionToItem;
+    QMap<QTreeWidgetItem *, QAction *> itemToAction;
+
+    // dynamic
+    ToolBarItem *currentToolBar;
+    QMap<ToolBarItem *, QListWidgetItem *> toolBarToItem;
+    QMap<QListWidgetItem *, ToolBarItem *> itemToToolBar;
+
+    // dynamic
+    QMap<QAction *, QListWidgetItem *> actionToCurrentItem;
+    QMap<QListWidgetItem *, QAction *> currentItemToAction;
+
+    QMap<QAction *, ToolBarItem *> widgetActionToToolBar;
+    QMap<ToolBarItem *, QSet<QAction *> > toolBarToWidgetActions;
+
+    QString separatorText;
+    Ui::QtToolBarDialog ui;
+};
+
+ToolBarItem *QtToolBarDialogPrivate::createItem(QToolBar *toolBar)
+{
+    if (!toolBar)
+        return 0;
+    ToolBarItem *item = new ToolBarItem(toolBar, toolBar->windowTitle());
+    allToolBarItems.insert(item);
+    return item;
+}
+
+ToolBarItem *QtToolBarDialogPrivate::createItem(const QString &toolBarName)
+{
+    ToolBarItem *item = new ToolBarItem(toolBarName);
+    allToolBarItems.insert(item);
+    return item;
+}
+
+void QtToolBarDialogPrivate::deleteItem(ToolBarItem *item)
+{
+    if (!allToolBarItems.contains(item))
+        return;
+    allToolBarItems.remove(item);
+    delete item;
+}
+
+void QtToolBarDialogPrivate::clearOld()
+{
+    ui.actionTree->clear();
+    ui.toolBarList->clear();
+    ui.currentToolBarList->clear();
+    ui.removeButton->setEnabled(false);
+    ui.newButton->setEnabled(false);
+    ui.upButton->setEnabled(false);
+    ui.downButton->setEnabled(false);
+    ui.leftButton->setEnabled(false);
+    ui.rightButton->setEnabled(false);
+
+    actionToItem.clear();
+    itemToAction.clear();
+    toolBarToItem.clear();
+    itemToToolBar.clear();
+    actionToCurrentItem.clear();
+    currentItemToAction.clear();
+    widgetActionToToolBar.clear();
+    toolBarToWidgetActions.clear();
+
+    toolBarItems.clear();
+    currentState.clear();
+    createdItems.clear();
+    removedItems.clear();
+    QSetIterator<ToolBarItem *> itItem(allToolBarItems);
+    while (itItem.hasNext())
+        delete itItem.next();
+    allToolBarItems.clear();
+
+    currentToolBar = 0;
+    currentAction = 0;
+}
+
+void QtToolBarDialogPrivate::fillNew()
+{
+    if (!toolBarManager)
+        return;
+
+    QTreeWidgetItem *item = new QTreeWidgetItem(ui.actionTree);
+    item->setText(0, separatorText);
+    ui.actionTree->setCurrentItem(item);
+    currentAction = item;
+    actionToItem.insert(0, item);
+    itemToAction.insert(item, 0);
+    QStringList categories = toolBarManager->categories();
+    QStringListIterator itCategory(categories);
+    while (itCategory.hasNext()) {
+        QString category = itCategory.next();
+        QTreeWidgetItem *categoryItem = new QTreeWidgetItem(ui.actionTree);
+        categoryItem->setText(0, category);
+        QList<QAction *> actions = toolBarManager->categoryActions(category);
+        QListIterator<QAction *> itAction(actions);
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+            item = new QTreeWidgetItem(categoryItem);
+            item->setText(0, action->text());
+            item->setIcon(0, action->icon());
+            item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+            actionToItem.insert(action, item);
+            itemToAction.insert(item, action);
+            if (toolBarManager->isWidgetAction(action)) {
+                item->setData(0, Qt::TextColorRole, QColor(Qt::blue));
+                widgetActionToToolBar.insert(action, 0);
+            }
+            item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
+        }
+        ui.actionTree->setItemExpanded(categoryItem, true);
+    }
+    //ui.actionTree->sortItems(0, Qt::AscendingOrder);
+
+    QMap<QToolBar *, QList<QAction *> > toolBars = toolBarManager->toolBarsActions();
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator it = toolBars.constBegin();
+    while (it != toolBars.constEnd()) {
+        QToolBar *toolBar = it.key();
+        ToolBarItem *tbItem = createItem(toolBar);
+        toolBarItems.insert(toolBar, tbItem);
+        QListWidgetItem *item = new QListWidgetItem(toolBar->windowTitle(),
+                ui.toolBarList);
+        toolBarToItem.insert(tbItem, item);
+        itemToToolBar.insert(item, tbItem);
+        QList<QAction *> actions = it.value();
+        QListIterator<QAction *> itAction(actions);
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+            if (toolBarManager->isWidgetAction(action)) {
+                widgetActionToToolBar.insert(action, tbItem);
+                toolBarToWidgetActions[tbItem].insert(action);
+            }
+        }
+        currentState.insert(tbItem, actions);
+        if (it == toolBars.constBegin())
+            ui.toolBarList->setCurrentItem(item);
+        if (isDefaultToolBar(tbItem))
+            item->setData(Qt::TextColorRole, QColor(Qt::darkGreen));
+        else
+            item->setFlags(item->flags() | Qt::ItemIsEditable);
+
+        ++it;
+    }
+    ui.toolBarList->sortItems();
+    setButtons();
+}
+
+bool QtToolBarDialogPrivate::isDefaultToolBar(ToolBarItem *item) const
+{
+    if (!item)
+        return false;
+    if (!item->toolBar())
+        return false;
+    return toolBarManager->isDefaultToolBar(item->toolBar());
+}
+
+void QtToolBarDialogPrivate::setButtons()
+{
+    bool newEnabled = false;
+    bool removeEnabled = false;
+    bool renameEnabled = false;
+    bool upEnabled = false;
+    bool downEnabled = false;
+    bool leftEnabled = false;
+    bool rightEnabled = false;
+
+    if (toolBarManager) {
+        newEnabled = true;
+        removeEnabled = !isDefaultToolBar(currentToolBar);
+        renameEnabled = removeEnabled;
+        QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+        if (currentToolBarAction) {
+            int row = ui.currentToolBarList->row(currentToolBarAction);
+            upEnabled = row > 0;
+            downEnabled = row < ui.currentToolBarList->count() - 1;
+            leftEnabled = true;
+        }
+        if (currentAction && currentToolBar)
+            rightEnabled = true;
+    }
+    ui.newButton->setEnabled(newEnabled);
+    ui.removeButton->setEnabled(removeEnabled);
+    ui.renameButton->setEnabled(renameEnabled);
+    ui.upButton->setEnabled(upEnabled);
+    ui.downButton->setEnabled(downEnabled);
+    ui.leftButton->setEnabled(leftEnabled);
+    ui.rightButton->setEnabled(rightEnabled);
+}
+
+void QtToolBarDialogPrivate::newClicked()
+{
+    QString toolBarName = QtToolBarDialog::tr("Custom Toolbar"); // = QInputDialog::getString();
+    // produce unique name
+    ToolBarItem *item = createItem(toolBarName);
+    currentState.insert(item, QList<QAction *>());
+    createdItems.insert(item);
+    QListWidgetItem *i = new QListWidgetItem(toolBarName, ui.toolBarList);
+    i->setFlags(i->flags() | Qt::ItemIsEditable);
+    ui.toolBarList->setCurrentItem(i);
+    itemToToolBar.insert(i, item);
+    toolBarToItem.insert(item, i);
+    ui.toolBarList->sortItems();
+    ui.toolBarList->setCurrentItem(i);
+    currentToolBarChanged(i);
+    renameClicked();
+}
+
+void QtToolBarDialogPrivate::removeToolBar(ToolBarItem *item)
+{
+    if (!item)
+        return;
+    if (item->toolBar() && toolBarManager->isDefaultToolBar(item->toolBar()))
+        return;
+    if (!toolBarToItem.contains(item))
+        return;
+    QListWidgetItem *i = toolBarToItem.value(item);
+    bool wasCurrent = false;
+    if (i == ui.toolBarList->currentItem())
+        wasCurrent = true;
+    int row = ui.toolBarList->row(i);
+    QMap<ToolBarItem *, QSet<QAction *> >::ConstIterator itToolBar =
+            toolBarToWidgetActions.find(item);
+    if (itToolBar != toolBarToWidgetActions.constEnd()) {
+        QSet<QAction *> actions = itToolBar.value();
+        QSetIterator<QAction *> itAction(actions);
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+            widgetActionToToolBar.insert(action, 0);
+        }
+        toolBarToWidgetActions.remove(item);
+    }
+
+    currentState.remove(item);
+    createdItems.remove(item);
+    toolBarToItem.remove(item);
+    itemToToolBar.remove(i);
+    delete i;
+    if (item->toolBar())
+        removedItems.insert(item);
+    else
+        deleteItem(item);
+    if (wasCurrent) {
+        if (row == ui.toolBarList->count())
+            row--;
+        if (row < 0)
+            ;
+        else
+            ui.toolBarList->setCurrentRow(row);
+    }
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::removeClicked()
+{
+    QListWidgetItem *i = ui.toolBarList->currentItem();
+    if (!i)
+        return;
+    ToolBarItem *item = itemToToolBar.value(i);
+    removeToolBar(item);
+}
+
+void QtToolBarDialogPrivate::defaultClicked()
+{
+    QMap<QToolBar *, QList<QAction *> > defaultToolBars = toolBarManager->defaultToolBars();
+    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = defaultToolBars.constBegin();
+    while (itToolBar != defaultToolBars.constEnd()) {
+        QToolBar *toolBar = itToolBar.key();
+        ToolBarItem *toolBarItem = toolBarItems.value(toolBar);
+
+        if (toolBarToWidgetActions.contains(toolBarItem)) {
+            QSetIterator<QAction *> itAction(toolBarToWidgetActions.value(toolBarItem));
+            while (itAction.hasNext())
+                widgetActionToToolBar.insert(itAction.next(), 0);
+            toolBarToWidgetActions.remove(toolBarItem);
+        }
+
+        currentState.remove(toolBarItem);
+
+        QListIterator<QAction *> itAction(itToolBar.value());
+        while (itAction.hasNext()) {
+            QAction *action = itAction.next();
+            if (toolBarManager->isWidgetAction(action)) {
+                ToolBarItem *otherToolBar = widgetActionToToolBar.value(action);
+                if (otherToolBar) {
+                    toolBarToWidgetActions[otherToolBar].remove(action);
+                    currentState[otherToolBar].removeAll(action);
+                }
+                widgetActionToToolBar.insert(action, toolBarItem);
+                toolBarToWidgetActions[toolBarItem].insert(action);
+            }
+        }
+        currentState.insert(toolBarItem, itToolBar.value());
+
+        ++itToolBar;
+    }
+    currentToolBarChanged(toolBarToItem.value(currentToolBar));
+
+    QList<ToolBarItem *> toolBars = currentState.keys();
+    QListIterator<ToolBarItem *> itTb(toolBars);
+    while (itTb.hasNext())
+        removeToolBar(itTb.next());
+}
+
+void QtToolBarDialogPrivate::okClicked()
+{
+    applyClicked();
+    q_ptr->accept();
+}
+
+void QtToolBarDialogPrivate::applyClicked()
+{
+    QMap<ToolBarItem *, QList<QAction *> > toolBars = currentState;
+    QMap<ToolBarItem *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
+    while (itToolBar != toolBars.constEnd()) {
+        ToolBarItem *item = itToolBar.key();
+        QToolBar *toolBar = item->toolBar();
+        if (toolBar) {
+            toolBarManager->setToolBar(toolBar, itToolBar.value());
+            toolBar->setWindowTitle(item->toolBarName());
+        }
+
+        ++itToolBar;
+    }
+
+    QSet<ToolBarItem *> toRemove = removedItems;
+    QSetIterator<ToolBarItem *> itRemove(toRemove);
+    while (itRemove.hasNext()) {
+        ToolBarItem *item = itRemove.next();
+        QToolBar *toolBar = item->toolBar();
+        removedItems.remove(item);
+        currentState.remove(item);
+        deleteItem(item);
+        if (toolBar)
+            toolBarManager->deleteToolBar(toolBar);
+    }
+
+    QSet<ToolBarItem *> toCreate = createdItems;
+    QSetIterator<ToolBarItem *> itCreate(toCreate);
+    while (itCreate.hasNext()) {
+        ToolBarItem *item = itCreate.next();
+        QString toolBarName = item->toolBarName();
+        createdItems.remove(item);
+        QList<QAction *> actions = currentState.value(item);
+        QToolBar *toolBar = toolBarManager->createToolBar(toolBarName);
+        item->setToolBar(toolBar);
+        toolBarManager->setToolBar(toolBar, actions);
+    }
+}
+
+void QtToolBarDialogPrivate::upClicked()
+{
+    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+    if (!currentToolBarAction)
+        return;
+    int row = ui.currentToolBarList->row(currentToolBarAction);
+    if (row == 0)
+        return;
+    ui.currentToolBarList->takeItem(row);
+    int newRow = row - 1;
+    ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
+    QList<QAction *> actions = currentState.value(currentToolBar);
+    QAction *action = actions.at(row);
+    actions.removeAt(row);
+    actions.insert(newRow, action);
+    currentState.insert(currentToolBar, actions);
+    ui.currentToolBarList->setCurrentItem(currentToolBarAction);
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::downClicked()
+{
+    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+    if (!currentToolBarAction)
+        return;
+    int row = ui.currentToolBarList->row(currentToolBarAction);
+    if (row == ui.currentToolBarList->count() - 1)
+        return;
+    ui.currentToolBarList->takeItem(row);
+    int newRow = row + 1;
+    ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
+    QList<QAction *> actions = currentState.value(currentToolBar);
+    QAction *action = actions.at(row);
+    actions.removeAt(row);
+    actions.insert(newRow, action);
+    currentState.insert(currentToolBar, actions);
+    ui.currentToolBarList->setCurrentItem(currentToolBarAction);
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::leftClicked()
+{
+    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+    if (!currentToolBarAction)
+        return;
+    int row = ui.currentToolBarList->row(currentToolBarAction);
+    currentState[currentToolBar].removeAt(row);
+    QAction *action = currentItemToAction.value(currentToolBarAction);
+    if (widgetActionToToolBar.contains(action)) {
+        ToolBarItem *item = widgetActionToToolBar.value(action);
+        if (item == currentToolBar) { // have to be
+            toolBarToWidgetActions[item].remove(action);
+            if (toolBarToWidgetActions[item].empty())
+                toolBarToWidgetActions.remove(item);
+        }
+        widgetActionToToolBar.insert(action, 0);
+    }
+    if (action)
+        actionToCurrentItem.remove(action);
+    currentItemToAction.remove(currentToolBarAction);
+    delete currentToolBarAction;
+    if (row == ui.currentToolBarList->count())
+        row--;
+    if (row >= 0) {
+        QListWidgetItem *item = ui.currentToolBarList->item(row);
+        ui.currentToolBarList->setCurrentItem(item);
+    }
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::rightClicked()
+{
+    if (!currentAction)
+        return;
+    if (!currentToolBar)
+        return;
+    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+
+    QAction *action = itemToAction.value(currentAction);
+    QListWidgetItem *item = 0;
+    if (action) {
+        if (currentState[currentToolBar].contains(action)) {
+            item = actionToCurrentItem.value(action);
+            if (item == currentToolBarAction)
+                return;
+            int row = ui.currentToolBarList->row(item);
+            ui.currentToolBarList->takeItem(row);
+            currentState[currentToolBar].removeAt(row);
+            // only reorder here
+        } else {
+            item = new QListWidgetItem(action->text());
+            item->setIcon(action->icon());
+            item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+            currentItemToAction.insert(item, action);
+            actionToCurrentItem.insert(action, item);
+            if (widgetActionToToolBar.contains(action)) {
+                item->setData(Qt::TextColorRole, QColor(Qt::blue));
+                ToolBarItem *toolBar = widgetActionToToolBar.value(action);
+                if (toolBar) {
+                    currentState[toolBar].removeAll(action);
+                    toolBarToWidgetActions[toolBar].remove(action);
+                    if (toolBarToWidgetActions[toolBar].empty())
+                        toolBarToWidgetActions.remove(toolBar);
+                }
+                widgetActionToToolBar.insert(action, currentToolBar);
+                toolBarToWidgetActions[currentToolBar].insert(action);
+            }
+        }
+    } else {
+        item = new QListWidgetItem(separatorText);
+        currentItemToAction.insert(item, 0);
+    }
+
+    int row = ui.currentToolBarList->count();
+    if (currentToolBarAction) {
+        row = ui.currentToolBarList->row(currentToolBarAction) + 1;
+    }
+    ui.currentToolBarList->insertItem(row, item);
+    currentState[currentToolBar].insert(row, action);
+    ui.currentToolBarList->setCurrentItem(item);
+
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::renameClicked()
+{
+    if (!currentToolBar)
+        return;
+
+    QListWidgetItem *item = toolBarToItem.value(currentToolBar);
+    ui.toolBarList->editItem(item);
+}
+
+void QtToolBarDialogPrivate::toolBarRenamed(QListWidgetItem *item)
+{
+    if (!currentToolBar)
+        return;
+
+    ToolBarItem *tbItem = itemToToolBar.value(item);
+    if (!tbItem)
+        return;
+    tbItem->setToolBarName(item->text());
+    //ui.toolBarList->sortItems();
+}
+
+void QtToolBarDialogPrivate::currentActionChanged(QTreeWidgetItem *current)
+{
+    if (itemToAction.contains(current))
+        currentAction = current;
+    else
+        currentAction = NULL;
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::currentToolBarChanged(QListWidgetItem *current)
+{
+    currentToolBar = itemToToolBar.value(current);
+    ui.currentToolBarList->clear();
+    actionToCurrentItem.clear();
+    currentItemToAction.clear();
+    setButtons();
+    if (!currentToolBar) {
+        return;
+    }
+    QList<QAction *> actions = currentState.value(currentToolBar);
+    QListIterator<QAction *> itAction(actions);
+    QListWidgetItem *first = 0;
+    while (itAction.hasNext()) {
+        QAction *action = itAction.next();
+        QString actionName = separatorText;
+        if (action)
+            actionName = action->text();
+        QListWidgetItem *item = new QListWidgetItem(actionName, ui.currentToolBarList);
+        if (action) {
+            item->setIcon(action->icon());
+            item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+            actionToCurrentItem.insert(action, item);
+            if (widgetActionToToolBar.contains(action))
+                item->setData(Qt::TextColorRole, QColor(Qt::blue));
+        }
+        currentItemToAction.insert(item, action);
+        if (!first)
+            first = item;
+    }
+    if (first)
+        ui.currentToolBarList->setCurrentItem(first);
+}
+
+void QtToolBarDialogPrivate::currentToolBarActionChanged(QListWidgetItem *)
+{
+    setButtons();
+}
+
+void QtToolBarDialogPrivate::cancelClicked()
+{
+    // just nothing
+    q_ptr->reject();
+}
+
+//////////////////////
+/*
+class FeedbackItemDelegate : public QItemDelegate
+{
+    Q_OBJECT
+public:
+    FeedbackItemDelegate(QObject *parent = 0) : QItemDelegate(parent) { }
+
+    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
+                    const QModelIndex & index) const;
+    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+void FeedbackItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+                            const QModelIndex &index) const
+{
+    if ()
+    painter->save();
+    QRect r = option.rect;
+    float yCentral = r.height() / 2.0;
+    float margin = 2.0;
+    float arrowWidth = 5.0;
+    float width = 20;
+    qDebug("rect: x %d, y %d, w %d, h %d", r.x(), r.y(), r.width(), r.height());
+    QLineF lineBase(0.0 + margin, r.y() + yCentral, width - margin, r.y() + yCentral);
+    QLineF lineArrowLeft(width - margin - arrowWidth, r.y() + yCentral - arrowWidth,
+                    width - margin, r.y() + yCentral);
+    QLineF lineArrowRight(width - margin - arrowWidth, r.y() + yCentral + arrowWidth,
+                    width - margin, r.y() + yCentral);
+    painter->drawLine(lineBase);
+    painter->drawLine(lineArrowLeft);
+    painter->drawLine(lineArrowRight);
+    painter->translate(QPoint(width, 0));
+    QItemDelegate::paint(painter, option, index);
+    painter->restore();
+}
+
+QSize FeedbackItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+            const QModelIndex &index) const
+{
+    //return QItemDelegate::sizeHint(option, index);
+    QSize s = QItemDelegate::sizeHint(option, index);
+    s.setWidth(s.width() - 20);
+    return s;
+}
+
+class QtToolBarListWidget : public QListWidget
+{
+    Q_OBJECT
+public:
+    QtToolBarListWidget(QWidget *parent) : QListWidget(parent), actionDrag(false) {}
+
+protected:
+    void startDrag(Qt::DropActions supportedActions);
+
+    void dragEnterEvent(QDragEnterEvent *event);
+    void dragMoveEvent(QDragMoveEvent *event);
+    void dragLeaveEvent(QDragLeaveEvent *);
+    void dropEvent(QDropEvent *event);
+
+    void setDragAction(const QString *action) { actionName = action; }
+private:
+    QPersistentModelIndex lastDropIndicator;
+    QString actionName;
+    bool actionDrag;
+};
+
+void QtToolBarListWidget::startDrag(Qt::DropActions supportedActions)
+{
+    QListWidgetItem *item = currentItem();
+    if (item) {
+        actionName = QString();
+        emit aboutToDrag(item);
+        if (!actionName.isEmpty()) {
+            QDrag *drag = new QDrag(this);
+            QMimeData *data = new QMimeData;
+            data->setData("action", actionName.toLocal8Bit().constData());
+            drag->setMimeData(data);
+            drag->start(supportedActions);
+        }
+    }
+}
+
+void QtToolBarListWidget::dragEnterEvent(QDragEnterEvent *event)
+{
+    const QMimeData *mime = event->mimeData();
+    actionDrag = mime->hasFormat("action");
+    if (actionDrag)
+        event->accept();
+    else
+        event->ignore();
+}
+
+void QtToolBarListWidget::dragMoveEvent(QDragMoveEvent *event)
+{
+    event->ignore();
+    if (actionDrag) {
+        QPoint p = event->pos();
+        QListWidgetItem *item = itemAt(p);
+        Indicator indic = QtToolBarListWidget::None;
+        if (item) {
+            QRect rect = visualItemRect(item);
+            if (p.y() - rect.top() < rect.height() / 2)
+                indic = QtToolBarListWidget::Above;
+            else
+                indic = QtToolBarListWidget::Below;
+        }
+        setIndicator(item, indic);
+        event->accept();
+    }
+}
+
+void QtToolBarListWidget::dragLeaveEvent(QDragLeaveEvent *)
+{
+    if (actionDrag) {
+        actionDrag = false;
+        setIndicator(item, QtToolBarListWidget::None);
+    }
+}
+
+void QtToolBarListWidget::dropEvent(QDropEvent *event)
+{
+    if (actionDrag) {
+        QListWidgetItem *item = indicatorItem();
+        Indicator indic = indicator();
+        QByteArray array = event->mimeData()->data("action");
+        QDataStream stream(&array, QIODevice::ReadOnly);
+        QString action;
+        stream >> action;
+        emit actionDropped(action, item, );
+
+        actionDrag = false;
+        setIndicator(item, QtToolBarListWidget::None);
+    }
+}
+*/
+
+/*! \class QtToolBarDialog
+    \internal
+    \inmodule QtDesigner
+    \since 4.4
+
+    \brief The QtToolBarDialog class provides a dialog for customizing
+    toolbars.
+
+    QtToolBarDialog allows the user to customize the toolbars for a
+    given main window.
+
+    \image qttoolbardialog.png
+
+    The dialog lets the users add, rename and remove custom toolbars.
+    Note that built-in toolbars are marked with a green color, and
+    cannot be removed or renamed.
+
+    The users can also add and remove actions from the toolbars. An
+    action can be added to many toolbars, but a toolbar can only
+    contain one instance of each action. Actions that contains a
+    widget are marked with a blue color in the list of actions, and
+    can only be added to one single toolbar.
+
+    Finally, the users can add separators to the toolbars.
+
+    The original toolbars can be restored by clicking the \gui
+    {Restore all} button. All custom toolbars will then be removed,
+    and all built-in toolbars will be restored to their original state.
+
+    The QtToolBarDialog class's functionality is controlled by an
+    instance of the QtToolBarManager class, and the main window is
+    specified using the QtToolBarManager::setMainWindow() function.
+
+    All you need to do to use QtToolBarDialog is to specify an
+    QtToolBarManager instance and call the QDialog::exec() slot:
+
+    \snippet doc/src/snippets/code/tools_shared_qttoolbardialog_qttoolbardialog.cpp 0
+
+    \sa QtToolBarManager
+*/
+
+/*!
+    Creates a toolbar dialog with the given \a parent and the specified
+    window \a flags.
+*/
+QtToolBarDialog::QtToolBarDialog(QWidget *parent, Qt::WindowFlags flags)
+    : QDialog(parent, flags), d_ptr(new QtToolBarDialogPrivate)
+{
+    d_ptr->q_ptr = this;
+    d_ptr->ui.setupUi(this);
+    d_ptr->separatorText = tr("< S E P A R A T O R >");
+
+    d_ptr->ui.actionTree->setColumnCount(1);
+    d_ptr->ui.actionTree->setRootIsDecorated(false);
+    d_ptr->ui.actionTree->header()->hide();
+
+    d_ptr->ui.upButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/up.png")));
+    d_ptr->ui.downButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/down.png")));
+    d_ptr->ui.leftButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/back.png")));
+    d_ptr->ui.rightButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/forward.png")));
+    d_ptr->ui.newButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/plus.png")));
+    d_ptr->ui.removeButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/minus.png")));
+
+    connect(d_ptr->ui.newButton, SIGNAL(clicked()), this, SLOT(newClicked()));
+    connect(d_ptr->ui.removeButton, SIGNAL(clicked()), this, SLOT(removeClicked()));
+    connect(d_ptr->ui.renameButton, SIGNAL(clicked()), this, SLOT(renameClicked()));
+    connect(d_ptr->ui.upButton, SIGNAL(clicked()), this, SLOT(upClicked()));
+    connect(d_ptr->ui.downButton, SIGNAL(clicked()), this, SLOT(downClicked()));
+    connect(d_ptr->ui.leftButton, SIGNAL(clicked()), this, SLOT(leftClicked()));
+    connect(d_ptr->ui.rightButton, SIGNAL(clicked()), this, SLOT(rightClicked()));
+
+    connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(defaultClicked()));
+    connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
+    connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
+    connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
+
+    connect(d_ptr->ui.actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
+                    this, SLOT(currentActionChanged(QTreeWidgetItem*)));
+    connect(d_ptr->ui.toolBarList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
+                    this, SLOT(currentToolBarChanged(QListWidgetItem*)));
+    connect(d_ptr->ui.currentToolBarList,
+                    SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
+                    this, SLOT(currentToolBarActionChanged(QListWidgetItem*)));
+
+    connect(d_ptr->ui.actionTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
+                    this, SLOT(rightClicked()));
+    connect(d_ptr->ui.currentToolBarList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
+                    this, SLOT(leftClicked()));
+    connect(d_ptr->ui.toolBarList, SIGNAL(itemChanged(QListWidgetItem*)),
+                    this, SLOT(toolBarRenamed(QListWidgetItem*)));
+}
+
+/*!
+    Destroys the toolbar dialog.
+*/
+QtToolBarDialog::~QtToolBarDialog()
+{
+    d_ptr->clearOld();
+}
+
+/*!
+    Connects the toolbar dialog to the given \a toolBarManager. Then,
+    when exec() is called, the toolbar dialog will operate using the
+    given \a toolBarManager.
+*/
+void QtToolBarDialog::setToolBarManager(QtToolBarManager *toolBarManager)
+{
+    if (d_ptr->toolBarManager == toolBarManager->d_ptr->manager)
+        return;
+    if (isVisible())
+        d_ptr->clearOld();
+    d_ptr->toolBarManager = toolBarManager->d_ptr->manager;
+    if (isVisible())
+        d_ptr->fillNew();
+}
+
+/*!
+    \reimp
+*/
+void QtToolBarDialog::showEvent(QShowEvent *event)
+{
+    if (!event->spontaneous())
+        d_ptr->fillNew();
+}
+
+/*!
+    \reimp
+*/
+void QtToolBarDialog::hideEvent(QHideEvent *event)
+{
+    if (!event->spontaneous())
+        d_ptr->clearOld();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qttoolbardialog.cpp"
+#include "moc_qttoolbardialog.h"
diff --git a/src/designer/designer/qttoolbardialog/qttoolbardialog.h b/src/designer/designer/qttoolbardialog/qttoolbardialog.h
new file mode 100644 (file)
index 0000000..3c6affd
--- /dev/null
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of Qt Designer.  This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTTOOLBARDIALOG_H
+#define QTTOOLBARDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QMainWindow;
+class QAction;
+class QToolBar;
+
+class QtToolBarManagerPrivate;
+
+class QtToolBarManager : public QObject
+{
+    Q_OBJECT
+public:
+
+    explicit QtToolBarManager(QObject *parent = 0);
+    ~QtToolBarManager();
+
+    void setMainWindow(QMainWindow *mainWindow);
+    QMainWindow *mainWindow() const;
+
+    void addAction(QAction *action, const QString &category);
+    void removeAction(QAction *action);
+
+    void addToolBar(QToolBar *toolBar, const QString &category);
+    void removeToolBar(QToolBar *toolBar);
+
+    QList<QToolBar *> toolBars() const;
+
+    QByteArray saveState(int version = 0) const;
+    bool restoreState(const QByteArray &state, int version = 0);
+
+private:
+
+    friend class QtToolBarDialog;
+    QScopedPointer<QtToolBarManagerPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QtToolBarManager)
+    Q_DISABLE_COPY(QtToolBarManager)
+};
+
+class QtToolBarDialogPrivate;
+
+class QtToolBarDialog : public QDialog
+{
+    Q_OBJECT
+public:
+
+    explicit QtToolBarDialog(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+    ~QtToolBarDialog();
+
+    void setToolBarManager(QtToolBarManager *toolBarManager);
+
+protected:
+
+    void showEvent(QShowEvent *event);
+    void hideEvent(QHideEvent *event);
+
+private:
+
+    QScopedPointer<QtToolBarDialogPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QtToolBarDialog)
+    Q_DISABLE_COPY(QtToolBarDialog)
+
+    Q_PRIVATE_SLOT(d_func(), void newClicked())
+    Q_PRIVATE_SLOT(d_func(), void removeClicked())
+    Q_PRIVATE_SLOT(d_func(), void defaultClicked())
+    Q_PRIVATE_SLOT(d_func(), void okClicked())
+    Q_PRIVATE_SLOT(d_func(), void applyClicked())
+    Q_PRIVATE_SLOT(d_func(), void cancelClicked())
+    Q_PRIVATE_SLOT(d_func(), void upClicked())
+    Q_PRIVATE_SLOT(d_func(), void downClicked())
+    Q_PRIVATE_SLOT(d_func(), void leftClicked())
+    Q_PRIVATE_SLOT(d_func(), void rightClicked())
+    Q_PRIVATE_SLOT(d_func(), void renameClicked())
+    Q_PRIVATE_SLOT(d_func(), void toolBarRenamed(QListWidgetItem *))
+    Q_PRIVATE_SLOT(d_func(), void currentActionChanged(QTreeWidgetItem *))
+    Q_PRIVATE_SLOT(d_func(), void currentToolBarChanged(QListWidgetItem *))
+    Q_PRIVATE_SLOT(d_func(), void currentToolBarActionChanged(QListWidgetItem *))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/designer/designer/qttoolbardialog/qttoolbardialog.qrc b/src/designer/designer/qttoolbardialog/qttoolbardialog.qrc
new file mode 100644 (file)
index 0000000..ce03366
--- /dev/null
@@ -0,0 +1,10 @@
+<RCC version="1.0">
+    <qresource prefix="/trolltech/qttoolbardialog">
+        <file>images/up.png</file>
+        <file>images/down.png</file>
+        <file>images/forward.png</file>
+        <file>images/back.png</file>
+        <file>images/plus.png</file>
+        <file>images/minus.png</file>
+    </qresource>
+</RCC>
diff --git a/src/designer/designer/qttoolbardialog/qttoolbardialog.ui b/src/designer/designer/qttoolbardialog/qttoolbardialog.ui
new file mode 100644 (file)
index 0000000..c4ad934
--- /dev/null
@@ -0,0 +1,207 @@
+<ui version="4.0" >
+ <class>QtToolBarDialog</class>
+ <widget class="QDialog" name="QtToolBarDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>583</width>
+    <height>508</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Customize Toolbars</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>8</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item rowspan="3" row="1" column="0" >
+    <widget class="QTreeWidget" name="actionTree" >
+     <column>
+      <property name="text" >
+       <string>1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item row="0" column="0" >
+    <widget class="QLabel" name="label" >
+     <property name="text" >
+      <string>Actions</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="2" >
+    <layout class="QHBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="label_2" >
+       <property name="text" >
+        <string>Toolbars</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="newButton" >
+       <property name="toolTip" >
+        <string>Add new toolbar</string>
+       </property>
+       <property name="text" >
+        <string>New</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="removeButton" >
+       <property name="toolTip" >
+        <string>Remove selected toolbar</string>
+       </property>
+       <property name="text" >
+        <string>Remove</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="renameButton" >
+       <property name="toolTip" >
+        <string>Rename toolbar</string>
+       </property>
+       <property name="text" >
+        <string>Rename</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="1" >
+    <layout class="QVBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QToolButton" name="upButton" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip" >
+        <string>Move action up</string>
+       </property>
+       <property name="text" >
+        <string>Up</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="leftButton" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip" >
+        <string>Remove action from toolbar</string>
+       </property>
+       <property name="text" >
+        <string>&lt;-</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="rightButton" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip" >
+        <string>Add action to toolbar</string>
+       </property>
+       <property name="text" >
+        <string>-></string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="downButton" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip" >
+        <string>Move action down</string>
+       </property>
+       <property name="text" >
+        <string>Down</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0" >
+        <size>
+         <width>29</width>
+         <height>16</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="2" >
+    <widget class="QListWidget" name="currentToolBarList" />
+   </item>
+   <item row="2" column="1" colspan="2" >
+    <widget class="QLabel" name="label_3" >
+     <property name="text" >
+      <string>Current Toolbar Actions</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1" colspan="2" >
+    <widget class="QListWidget" name="toolBarList" />
+   </item>
+   <item row="5" column="0" colspan="3" >
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>newButton</tabstop>
+  <tabstop>removeButton</tabstop>
+  <tabstop>renameButton</tabstop>
+  <tabstop>toolBarList</tabstop>
+  <tabstop>upButton</tabstop>
+  <tabstop>leftButton</tabstop>
+  <tabstop>rightButton</tabstop>
+  <tabstop>downButton</tabstop>
+  <tabstop>currentToolBarList</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/designer/designer/saveformastemplate.cpp b/src/designer/designer/saveformastemplate.cpp
new file mode 100644 (file)
index 0000000..9614209
--- /dev/null
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "saveformastemplate.h"
+#include "qdesigner_settings.h"
+
+#include <QtCore/QFile>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+SaveFormAsTemplate::SaveFormAsTemplate(QDesignerFormEditorInterface *core,
+                                       QDesignerFormWindowInterface *formWindow,
+                                       QWidget *parent)
+    : QDialog(parent, Qt::Sheet),
+      m_core(core),
+      m_formWindow(formWindow)
+{
+    ui.setupUi(this);
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+    ui.templateNameEdit->setText(formWindow->mainContainer()->objectName());
+    ui.templateNameEdit->selectAll();
+
+    ui.templateNameEdit->setFocus();
+
+    QStringList paths = QDesignerSettings(m_core).formTemplatePaths();
+    ui.categoryCombo->addItems(paths);
+    ui.categoryCombo->addItem(tr("Add path..."));
+    m_addPathIndex = ui.categoryCombo->count() - 1;
+    connect(ui.templateNameEdit, SIGNAL(textChanged(QString)),
+            this, SLOT(updateOKButton(QString)));
+    connect(ui.categoryCombo, SIGNAL(activated(int)), this, SLOT(checkToAddPath(int)));
+}
+
+SaveFormAsTemplate::~SaveFormAsTemplate()
+{
+}
+
+void SaveFormAsTemplate::accept()
+{
+    QString templateFileName = ui.categoryCombo->currentText();
+    templateFileName += QLatin1Char('/');
+    const QString name = ui.templateNameEdit->text();
+    templateFileName +=  name;
+    const QString extension = QLatin1String(".ui");
+    if (!templateFileName.endsWith(extension))
+        templateFileName.append(extension);
+    QFile file(templateFileName);
+
+    if (file.exists()) {
+        QMessageBox msgBox(QMessageBox::Information, tr("Template Exists"),
+                        tr("A template with the name %1 already exists.\n"
+                           "Do you want overwrite the template?").arg(name), QMessageBox::Cancel, m_formWindow);
+        msgBox.setDefaultButton(QMessageBox::Cancel);
+        QPushButton *overwriteButton = msgBox.addButton(tr("Overwrite Template"), QMessageBox::AcceptRole);
+        msgBox.exec();
+        if (msgBox.clickedButton() != overwriteButton)
+            return;
+    }
+
+    while (!file.open(QFile::WriteOnly)) {
+        if (QMessageBox::information(m_formWindow, tr("Open Error"),
+            tr("There was an error opening template %1 for writing. Reason: %2").arg(name).arg(file.errorString()),
+            QMessageBox::Retry|QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) {
+            return;
+        }
+    }
+
+    const QString origName = m_formWindow->fileName();
+    // ensure m_formWindow->contents() will convert properly resource paths to relative paths
+    // (relative to template location, not to the current form location)
+    m_formWindow->setFileName(templateFileName);
+    QByteArray ba = m_formWindow->contents().toUtf8();
+    m_formWindow->setFileName(origName);
+    while (file.write(ba) != ba.size()) {
+        if (QMessageBox::information(m_formWindow, tr("Write Error"),
+            tr("There was an error writing the template %1 to disk. Reason: %2").arg(name).arg(file.errorString()),
+            QMessageBox::Retry|QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) {
+                file.close();
+                file.remove();
+                return;
+            }
+            file.reset();
+    }
+    // update the list of places too...
+    QStringList sl;
+    for (int i = 0; i < m_addPathIndex; ++i)
+        sl << ui.categoryCombo->itemText(i);
+
+    QDesignerSettings(m_core).setFormTemplatePaths(sl);
+
+    QDialog::accept();
+}
+
+void SaveFormAsTemplate::updateOKButton(const QString &str)
+{
+    QPushButton *okButton = ui.buttonBox->button(QDialogButtonBox::Ok);
+    okButton->setEnabled(!str.isEmpty());
+}
+
+QString  SaveFormAsTemplate::chooseTemplatePath(QWidget *parent)
+{
+    QString rc = QFileDialog::getExistingDirectory(parent,
+                                                   tr("Pick a directory to save templates in"));
+    if (rc.isEmpty())
+        return rc;
+
+    if (rc.endsWith(QDir::separator()))
+        rc.remove(rc.size() - 1, 1);
+    return rc;
+}
+
+void SaveFormAsTemplate::checkToAddPath(int itemIndex)
+{
+    if (itemIndex != m_addPathIndex)
+        return;
+
+    const QString dir = chooseTemplatePath(this);
+    if (dir.isEmpty()) {
+        ui.categoryCombo->setCurrentIndex(0);
+        return;
+    }
+
+    ui.categoryCombo->insertItem(m_addPathIndex, dir);
+    ui.categoryCombo->setCurrentIndex(m_addPathIndex);
+    ++m_addPathIndex;
+}
+
+QT_END_NAMESPACE
+#include <moc_saveformastemplate.h>
diff --git a/src/designer/designer/saveformastemplate.h b/src/designer/designer/saveformastemplate.h
new file mode 100644 (file)
index 0000000..25c957e
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAVEFORMASTEMPLATE_H
+#define SAVEFORMASTEMPLATE_H
+
+#include "ui_saveformastemplate.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class SaveFormAsTemplate: public QDialog
+{
+    Q_OBJECT
+public:
+    explicit SaveFormAsTemplate(QDesignerFormEditorInterface *m_core,
+                                QDesignerFormWindowInterface *formWindow,
+                                QWidget *parent = 0);
+    virtual ~SaveFormAsTemplate();
+
+private slots:
+    void accept();
+    void updateOKButton(const QString &str);
+    void checkToAddPath(int itemIndex);
+
+private:
+    static QString chooseTemplatePath(QWidget *parent);
+
+    Ui::SaveFormAsTemplate ui;
+    QDesignerFormEditorInterface *m_core;
+    QDesignerFormWindowInterface *m_formWindow;
+    int m_addPathIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // SAVEFORMASTEMPLATE_H
diff --git a/src/designer/designer/saveformastemplate.ui b/src/designer/designer/saveformastemplate.ui
new file mode 100644 (file)
index 0000000..9be3c80
--- /dev/null
@@ -0,0 +1,166 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>SaveFormAsTemplate</class>
+ <widget class="QDialog" name="SaveFormAsTemplate" >
+  <property name="windowTitle" >
+   <string>Save Form As Template</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <layout class="QFormLayout" >
+     <item row="0" column="0" >
+      <widget class="QLabel" name="label" >
+       <property name="frameShape" >
+        <enum>QFrame::NoFrame</enum>
+       </property>
+       <property name="frameShadow" >
+        <enum>QFrame::Plain</enum>
+       </property>
+       <property name="text" >
+        <string>&amp;Name:</string>
+       </property>
+       <property name="textFormat" >
+        <enum>Qt::AutoText</enum>
+       </property>
+       <property name="buddy" >
+        <cstring>templateNameEdit</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1" >
+      <widget class="QLineEdit" name="templateNameEdit" >
+       <property name="minimumSize" >
+        <size>
+         <width>222</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="text" >
+        <string/>
+       </property>
+       <property name="echoMode" >
+        <enum>QLineEdit::Normal</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0" >
+      <widget class="QLabel" name="label_2" >
+       <property name="frameShape" >
+        <enum>QFrame::NoFrame</enum>
+       </property>
+       <property name="frameShadow" >
+        <enum>QFrame::Plain</enum>
+       </property>
+       <property name="text" >
+        <string>&amp;Category:</string>
+       </property>
+       <property name="textFormat" >
+        <enum>Qt::AutoText</enum>
+       </property>
+       <property name="buddy" >
+        <cstring>categoryCombo</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1" >
+      <widget class="QComboBox" name="categoryCombo" />
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QFrame" name="horizontalLine" >
+     <property name="frameShape" >
+      <enum>QFrame::HLine</enum>
+     </property>
+     <property name="frameShadow" >
+      <enum>QFrame::Sunken</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>SaveFormAsTemplate</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>256</x>
+     <y>124</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>113</x>
+     <y>143</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>SaveFormAsTemplate</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>332</x>
+     <y>127</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>372</x>
+     <y>147</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/designer/designer/uifile.icns b/src/designer/designer/uifile.icns
new file mode 100644 (file)
index 0000000..2473ea4
Binary files /dev/null and b/src/designer/designer/uifile.icns differ
diff --git a/src/designer/designer/versiondialog.cpp b/src/designer/designer/versiondialog.cpp
new file mode 100644 (file)
index 0000000..8b1c89e
--- /dev/null
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QVector>
+#include <QtGui/qevent.h>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include <QtGui/QStyleOption>
+#include "versiondialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class VersionLabel : public QLabel
+{
+    Q_OBJECT
+public:
+    VersionLabel(QWidget *parent = 0);
+
+signals:
+    void triggered();
+
+protected:
+    void mousePressEvent(QMouseEvent *me);
+    void mouseMoveEvent(QMouseEvent *me);
+    void mouseReleaseEvent(QMouseEvent *me);
+    void paintEvent(QPaintEvent *pe);
+private:
+    QVector<QPoint> hitPoints;
+    QVector<QPoint> missPoints;
+    QPainterPath m_path;
+    bool secondStage;
+    bool m_pushed;
+};
+
+VersionLabel::VersionLabel(QWidget *parent)
+        : QLabel(parent), secondStage(false), m_pushed(false)
+{
+    setPixmap(QPixmap(QLatin1String(":/trolltech/designer/images/designer.png")));
+    hitPoints.append(QPoint(56, 25));
+    hitPoints.append(QPoint(29, 55));
+    hitPoints.append(QPoint(56, 87));
+    hitPoints.append(QPoint(82, 55));
+    hitPoints.append(QPoint(58, 56));
+
+    secondStage = false;
+    m_pushed = false;
+}
+
+void VersionLabel::mousePressEvent(QMouseEvent *me)
+{
+    if (me->button() == Qt::LeftButton) {
+        if (!secondStage) {
+            m_path = QPainterPath(me->pos());
+        } else {
+            m_pushed = true;
+            update();
+        }
+    }
+}
+
+void VersionLabel::mouseMoveEvent(QMouseEvent *me)
+{
+    if (me->buttons() & Qt::LeftButton)
+        if (!secondStage)
+            m_path.lineTo(me->pos());
+}
+
+void VersionLabel::mouseReleaseEvent(QMouseEvent *me)
+{
+    if (me->button() == Qt::LeftButton) {
+        if (!secondStage) {
+            m_path.lineTo(me->pos());
+            bool gotIt = true;
+            foreach(const QPoint &pt, hitPoints) {
+                if (!m_path.contains(pt)) {
+                    gotIt = false;
+                    break;
+                }
+            }
+            if (gotIt) {
+                foreach(const QPoint &pt, missPoints) {
+                    if (m_path.contains(pt)) {
+                        gotIt = false;
+                        break;
+                    }
+                }
+            }
+            if (gotIt && !secondStage) {
+                secondStage = true;
+                m_path = QPainterPath();
+                update();
+            }
+        } else {
+            m_pushed = false;
+            update();
+            emit triggered();
+        }
+    }
+}
+
+void VersionLabel::paintEvent(QPaintEvent *pe)
+{
+    if (secondStage) {
+        QPainter p(this);
+        QStyleOptionButton opt;
+        opt.init(this);
+        if (!m_pushed)
+            opt.state |= QStyle::State_Raised;
+        else
+            opt.state |= QStyle::State_Sunken;
+        opt.state &= ~QStyle::State_HasFocus;
+        style()->drawControl(QStyle::CE_PushButtonBevel, &opt, &p, this);
+    }
+    QLabel::paintEvent(pe);
+}
+
+VersionDialog::VersionDialog(QWidget *parent)
+    : QDialog(parent
+#ifdef Q_WS_MAC
+            , Qt::Tool
+#endif
+            )
+{
+    setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) | Qt::MSWindowsFixedSizeDialogHint);
+    QGridLayout *layout = new QGridLayout(this);
+    VersionLabel *label = new VersionLabel;
+    QLabel *lbl = new QLabel;
+    QString version = tr("<h3>%1</h3><br/><br/>Version %2");
+    version = version.arg(tr("Qt Designer")).arg(QLatin1String(QT_VERSION_STR));
+    version.append(tr("<br/>Qt Designer is a graphical user interface designer for Qt applications.<br/>"));
+
+    lbl->setText(tr("%1"
+                    "<br/>Copyright (C) 2015 The Qt Company Ltd."
+                    ).arg(version));
+
+    lbl->setWordWrap(true);
+    lbl->setOpenExternalLinks(true);
+
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+    connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
+    connect(label, SIGNAL(triggered()), this, SLOT(accept()));
+    layout->addWidget(label, 0, 0, 1, 1);
+    layout->addWidget(lbl, 0, 1, 4, 4);
+    layout->addWidget(buttonBox, 4, 2, 1, 1);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_versiondialog.cpp"
+#include "moc_versiondialog.h"
diff --git a/src/designer/designer/versiondialog.h b/src/designer/designer/versiondialog.h
new file mode 100644 (file)
index 0000000..6ac781d
--- /dev/null
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VERSIONDIALOG_H
+#define VERSIONDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class VersionDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit VersionDialog(QWidget *parent);
+};
+
+QT_END_NAMESPACE
+
+#endif